stage2 now supports using stage1 as a backend for compiling zig code
* move stage2.cpp code into zig0.cpp for simplicity * add -ftime-report and some more CLI options to stage2 * stage2 compites the llvm cpu features string * classifyFileExt understands more file extensions * correction to generateBuiltinZigSource using the wrong allocator (thanks dbandstra!) * stage2 is now able to build hello.zig into hello.o using stage1 as a library however it fails linking due to missing compiler-rt * remove dead code * simplify zig0 builtin.zig source * fix not resolving builtin.zig source path causing duplicate imports * fix stage1.h not being valid C code * fix stage2.h not being valid C codemaster
parent
333b12a8f9
commit
2ef68631cb
|
@ -1,3 +1,6 @@
|
|||
* build & link against compiler-rt
|
||||
* build & link against freestanding libc
|
||||
* Cache integration for stage1 zig code compilation
|
||||
* `zig test`
|
||||
* `zig build`
|
||||
* `-ftime-report`
|
||||
|
@ -14,10 +17,7 @@
|
|||
- using it as a preprocessor (-E)
|
||||
- try building some software
|
||||
* support rpaths in ELF linker code
|
||||
* build & link against compiler-rt
|
||||
- stage1 C++ code integration
|
||||
* repair @cImport
|
||||
* build & link against freestanding libc
|
||||
* add CLI support for a way to pass extra flags to c source files
|
||||
* capture lld stdout/stderr better
|
||||
* musl
|
||||
|
@ -35,10 +35,12 @@
|
|||
* implement emit-h in stage2
|
||||
* implement -fno-emit-bin
|
||||
* audit the base cache hash
|
||||
* --main-pkg-path
|
||||
* audit the CLI options for stage2
|
||||
* `zig init-lib`
|
||||
* `zig init-exe`
|
||||
* `zig run`
|
||||
* restore error messages for stage2_add_link_lib
|
||||
|
||||
* implement serialization/deserialization of incremental compilation metadata
|
||||
* incremental compilation - implement detection of which source files changed
|
||||
|
|
|
@ -258,7 +258,6 @@ find_package(Threads)
|
|||
# This is our shim which will be replaced by stage1.zig.
|
||||
set(ZIG0_SOURCES
|
||||
"${CMAKE_SOURCE_DIR}/src/zig0.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/src/stage2.cpp"
|
||||
)
|
||||
|
||||
set(ZIG_SOURCES
|
||||
|
|
|
@ -19,6 +19,7 @@ const libunwind = @import("libunwind.zig");
|
|||
const fatal = @import("main.zig").fatal;
|
||||
const Module = @import("Module.zig");
|
||||
const Cache = @import("Cache.zig");
|
||||
const stage1 = @import("stage1.zig");
|
||||
|
||||
/// General-purpose allocator. Used for both temporary and long-term storage.
|
||||
gpa: *Allocator,
|
||||
|
@ -26,6 +27,7 @@ gpa: *Allocator,
|
|||
arena_state: std.heap.ArenaAllocator.State,
|
||||
bin_file: *link.File,
|
||||
c_object_table: std.AutoArrayHashMapUnmanaged(*CObject, void) = .{},
|
||||
stage1_module: ?*stage1.Module,
|
||||
|
||||
link_error_flags: link.File.ErrorFlags = .{},
|
||||
|
||||
|
@ -122,6 +124,8 @@ const Job = union(enum) {
|
|||
|
||||
/// Generate builtin.zig source code and write it into the correct place.
|
||||
generate_builtin_zig: void,
|
||||
/// Use stage1 C++ code to compile zig code into an object file.
|
||||
stage1_module: void,
|
||||
};
|
||||
|
||||
pub const CObject = struct {
|
||||
|
@ -274,6 +278,7 @@ pub const InitOptions = struct {
|
|||
strip: bool = false,
|
||||
single_threaded: bool = false,
|
||||
is_native_os: bool,
|
||||
time_report: bool = false,
|
||||
link_eh_frame_hdr: bool = false,
|
||||
linker_script: ?[]const u8 = null,
|
||||
version_script: ?[]const u8 = null,
|
||||
|
@ -288,12 +293,20 @@ pub const InitOptions = struct {
|
|||
clang_passthrough_mode: bool = false,
|
||||
verbose_cc: bool = false,
|
||||
verbose_link: bool = false,
|
||||
verbose_tokenize: bool = false,
|
||||
verbose_ast: bool = false,
|
||||
verbose_ir: bool = false,
|
||||
verbose_llvm_ir: bool = false,
|
||||
verbose_cimport: bool = false,
|
||||
verbose_llvm_cpu_features: bool = false,
|
||||
is_test: bool = false,
|
||||
stack_size_override: ?u64 = null,
|
||||
self_exe_path: ?[]const u8 = null,
|
||||
version: ?std.builtin.Version = null,
|
||||
libc_installation: ?*const LibCInstallation = null,
|
||||
machine_code_model: std.builtin.CodeModel = .default,
|
||||
/// This is for stage1 and should be deleted upon completion of self-hosting.
|
||||
color: @import("main.zig").Color = .Auto,
|
||||
};
|
||||
|
||||
pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
|
||||
|
@ -332,11 +345,27 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
|
|||
{
|
||||
break :blk true;
|
||||
}
|
||||
|
||||
if (build_options.is_stage1) {
|
||||
// If stage1 generates an object file, self-hosted linker is not
|
||||
// yet sophisticated enough to handle that.
|
||||
break :blk options.root_pkg != null;
|
||||
}
|
||||
|
||||
break :blk false;
|
||||
};
|
||||
|
||||
// Make a decision on whether to use LLVM or our own backend.
|
||||
const use_llvm = if (options.use_llvm) |explicit| explicit else blk: {
|
||||
// If we have no zig code to compile, no need for LLVM.
|
||||
if (options.root_pkg == null)
|
||||
break :blk false;
|
||||
|
||||
// If we are the stage1 compiler, we depend on the stage1 c++ llvm backend
|
||||
// to compile zig code.
|
||||
if (build_options.is_stage1)
|
||||
break :blk true;
|
||||
|
||||
// We would want to prefer LLVM for release builds when it is available, however
|
||||
// we don't have an LLVM backend yet :)
|
||||
// We would also want to prefer LLVM for architectures that we don't have self-hosted support for too.
|
||||
|
@ -580,6 +609,118 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
|
|||
.ReleaseFast, .ReleaseSmall => false,
|
||||
};
|
||||
|
||||
const llvm_cpu_features: ?[*:0]const u8 = if (build_options.have_llvm and use_llvm) blk: {
|
||||
var buf = std.ArrayList(u8).init(arena);
|
||||
for (options.target.cpu.arch.allFeaturesList()) |feature, index_usize| {
|
||||
const index = @intCast(Target.Cpu.Feature.Set.Index, index_usize);
|
||||
const is_enabled = options.target.cpu.features.isEnabled(index);
|
||||
|
||||
if (feature.llvm_name) |llvm_name| {
|
||||
const plus_or_minus = "-+"[@boolToInt(is_enabled)];
|
||||
try buf.ensureCapacity(buf.items.len + 2 + llvm_name.len);
|
||||
buf.appendAssumeCapacity(plus_or_minus);
|
||||
buf.appendSliceAssumeCapacity(llvm_name);
|
||||
buf.appendSliceAssumeCapacity(",");
|
||||
}
|
||||
}
|
||||
assert(mem.endsWith(u8, buf.items, ","));
|
||||
buf.items[buf.items.len - 1] = 0;
|
||||
buf.shrink(buf.items.len);
|
||||
break :blk buf.items[0 .. buf.items.len - 1 :0].ptr;
|
||||
} else null;
|
||||
|
||||
const stage1_module: ?*stage1.Module = if (build_options.is_stage1 and use_llvm) blk: {
|
||||
// Here we use the legacy stage1 C++ compiler to compile Zig code.
|
||||
const stage2_target = try arena.create(stage1.Stage2Target);
|
||||
stage2_target.* = .{
|
||||
.arch = @enumToInt(options.target.cpu.arch) + 1, // skip over ZigLLVM_UnknownArch
|
||||
.os = @enumToInt(options.target.os.tag),
|
||||
.abi = @enumToInt(options.target.abi),
|
||||
.is_native_os = options.is_native_os,
|
||||
.is_native_cpu = false, // Only true when bootstrapping the compiler.
|
||||
.llvm_cpu_name = if (options.target.cpu.model.llvm_name) |s| s.ptr else null,
|
||||
.llvm_cpu_features = llvm_cpu_features.?,
|
||||
};
|
||||
const progress = try arena.create(std.Progress);
|
||||
const main_progress_node = try progress.start("", 100);
|
||||
if (options.color == .Off) progress.terminal = null;
|
||||
|
||||
const mod = module.?;
|
||||
const main_zig_file = mod.root_pkg.root_src_path;
|
||||
const zig_lib_dir = options.zig_lib_directory.path.?;
|
||||
const builtin_sub = &[_][]const u8{"builtin.zig"};
|
||||
const builtin_zig_path = try mod.zig_cache_artifact_directory.join(arena, builtin_sub);
|
||||
|
||||
const stage1_module = stage1.create(
|
||||
@enumToInt(options.optimize_mode),
|
||||
undefined,
|
||||
0, // TODO --main-pkg-path
|
||||
main_zig_file.ptr,
|
||||
main_zig_file.len,
|
||||
zig_lib_dir.ptr,
|
||||
zig_lib_dir.len,
|
||||
stage2_target,
|
||||
options.is_test,
|
||||
) orelse return error.OutOfMemory;
|
||||
|
||||
const output_dir = bin_directory.path orelse ".";
|
||||
|
||||
const stage1_pkg = try arena.create(stage1.Pkg);
|
||||
stage1_pkg.* = .{
|
||||
.name_ptr = undefined,
|
||||
.name_len = 0,
|
||||
.path_ptr = undefined,
|
||||
.path_len = 0,
|
||||
.children_ptr = undefined,
|
||||
.children_len = 0,
|
||||
.parent = null,
|
||||
};
|
||||
|
||||
stage1_module.* = .{
|
||||
.root_name_ptr = root_name.ptr,
|
||||
.root_name_len = root_name.len,
|
||||
.output_dir_ptr = output_dir.ptr,
|
||||
.output_dir_len = output_dir.len,
|
||||
.builtin_zig_path_ptr = builtin_zig_path.ptr,
|
||||
.builtin_zig_path_len = builtin_zig_path.len,
|
||||
.test_filter_ptr = "",
|
||||
.test_filter_len = 0,
|
||||
.test_name_prefix_ptr = "",
|
||||
.test_name_prefix_len = 0,
|
||||
.userdata = @ptrToInt(comp),
|
||||
.root_pkg = stage1_pkg,
|
||||
.code_model = @enumToInt(options.machine_code_model),
|
||||
.subsystem = stage1.TargetSubsystem.Auto,
|
||||
.err_color = @enumToInt(options.color),
|
||||
.pic = pic,
|
||||
.link_libc = options.link_libc,
|
||||
.link_libcpp = options.link_libcpp,
|
||||
.strip = options.strip,
|
||||
.is_single_threaded = single_threaded,
|
||||
.dll_export_fns = dll_export_fns,
|
||||
.link_mode_dynamic = link_mode == .Dynamic,
|
||||
.valgrind_enabled = valgrind,
|
||||
.function_sections = options.function_sections orelse false,
|
||||
.enable_stack_probing = stack_check,
|
||||
.enable_time_report = options.time_report,
|
||||
.enable_stack_report = false,
|
||||
.dump_analysis = false,
|
||||
.enable_doc_generation = false,
|
||||
.emit_bin = true,
|
||||
.emit_asm = false,
|
||||
.emit_llvm_ir = false,
|
||||
.test_is_evented = false,
|
||||
.verbose_tokenize = options.verbose_tokenize,
|
||||
.verbose_ast = options.verbose_ast,
|
||||
.verbose_ir = options.verbose_ir,
|
||||
.verbose_llvm_ir = options.verbose_llvm_ir,
|
||||
.verbose_cimport = options.verbose_cimport,
|
||||
.verbose_llvm_cpu_features = options.verbose_llvm_cpu_features,
|
||||
.main_progress_node = main_progress_node,
|
||||
};
|
||||
break :blk stage1_module;
|
||||
} else null;
|
||||
|
||||
const bin_file = try link.File.openPath(gpa, .{
|
||||
.directory = bin_directory,
|
||||
.sub_path = emit_bin.basename,
|
||||
|
@ -626,6 +767,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
|
|||
.machine_code_model = options.machine_code_model,
|
||||
.dll_export_fns = dll_export_fns,
|
||||
.error_return_tracing = error_return_tracing,
|
||||
.llvm_cpu_features = llvm_cpu_features,
|
||||
});
|
||||
errdefer bin_file.destroy();
|
||||
|
||||
|
@ -635,6 +777,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
|
|||
.zig_lib_directory = options.zig_lib_directory,
|
||||
.zig_cache_directory = options.zig_cache_directory,
|
||||
.bin_file = bin_file,
|
||||
.stage1_module = stage1_module,
|
||||
.work_queue = std.fifo.LinearFifo(Job, .Dynamic).init(gpa),
|
||||
.keep_source_files_loaded = options.keep_source_files_loaded,
|
||||
.use_clang = use_clang,
|
||||
|
@ -681,6 +824,10 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
|
|||
try comp.work_queue.writeItem(.{ .libunwind = {} });
|
||||
}
|
||||
|
||||
if (comp.stage1_module) |module| {
|
||||
try comp.work_queue.writeItem(.{ .stage1_module = {} });
|
||||
}
|
||||
|
||||
return comp;
|
||||
}
|
||||
|
||||
|
@ -689,6 +836,11 @@ pub fn destroy(self: *Compilation) void {
|
|||
self.bin_file.destroy();
|
||||
if (optional_module) |module| module.deinit();
|
||||
|
||||
if (self.stage1_module) |module| {
|
||||
module.main_progress_node.?.end();
|
||||
module.destroy();
|
||||
}
|
||||
|
||||
const gpa = self.gpa;
|
||||
self.work_queue.deinit();
|
||||
|
||||
|
@ -997,6 +1149,10 @@ pub fn performAllTheWork(self: *Compilation) error{OutOfMemory}!void {
|
|||
fatal("unable to update builtin.zig file: {}", .{@errorName(err)});
|
||||
};
|
||||
},
|
||||
.stage1_module => {
|
||||
// This Job is only queued up if there is a zig module.
|
||||
self.stage1_module.?.build_object();
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1365,7 +1521,7 @@ pub fn addCCArgs(
|
|||
try argv.append("-fPIC");
|
||||
}
|
||||
},
|
||||
.so, .assembly, .ll, .bc, .unknown => {},
|
||||
.shared_library, .assembly, .ll, .bc, .unknown, .static_library, .object, .zig, .zir => {},
|
||||
}
|
||||
if (out_dep_path) |p| {
|
||||
try argv.appendSlice(&[_][]const u8{ "-MD", "-MV", "-MF", p });
|
||||
|
@ -1445,17 +1601,39 @@ pub const FileExt = enum {
|
|||
ll,
|
||||
bc,
|
||||
assembly,
|
||||
so,
|
||||
shared_library,
|
||||
object,
|
||||
static_library,
|
||||
zig,
|
||||
zir,
|
||||
unknown,
|
||||
|
||||
pub fn clangSupportsDepFile(ext: FileExt) bool {
|
||||
return switch (ext) {
|
||||
.c, .cpp, .h => true,
|
||||
.ll, .bc, .assembly, .so, .unknown => false,
|
||||
|
||||
.ll,
|
||||
.bc,
|
||||
.assembly,
|
||||
.shared_library,
|
||||
.object,
|
||||
.static_library,
|
||||
.zig,
|
||||
.zir,
|
||||
.unknown,
|
||||
=> false,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
pub fn hasObjectExt(filename: []const u8) bool {
|
||||
return mem.endsWith(u8, filename, ".o") or mem.endsWith(u8, filename, ".obj");
|
||||
}
|
||||
|
||||
pub fn hasStaticLibraryExt(filename: []const u8) bool {
|
||||
return mem.endsWith(u8, filename, ".a") or mem.endsWith(u8, filename, ".lib");
|
||||
}
|
||||
|
||||
pub fn hasCExt(filename: []const u8) bool {
|
||||
return mem.endsWith(u8, filename, ".c");
|
||||
}
|
||||
|
@ -1471,6 +1649,32 @@ pub fn hasAsmExt(filename: []const u8) bool {
|
|||
return mem.endsWith(u8, filename, ".s") or mem.endsWith(u8, filename, ".S");
|
||||
}
|
||||
|
||||
pub fn hasSharedLibraryExt(filename: []const u8) bool {
|
||||
if (mem.endsWith(u8, filename, ".so") or
|
||||
mem.endsWith(u8, filename, ".dll") or
|
||||
mem.endsWith(u8, filename, ".dylib"))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
// Look for .so.X, .so.X.Y, .so.X.Y.Z
|
||||
var it = mem.split(filename, ".");
|
||||
_ = it.next().?;
|
||||
var so_txt = it.next() orelse return false;
|
||||
while (!mem.eql(u8, so_txt, "so")) {
|
||||
so_txt = it.next() orelse return false;
|
||||
}
|
||||
const n1 = it.next() orelse return false;
|
||||
const n2 = it.next();
|
||||
const n3 = it.next();
|
||||
|
||||
_ = std.fmt.parseInt(u32, n1, 10) catch return false;
|
||||
if (n2) |x| _ = std.fmt.parseInt(u32, x, 10) catch return false;
|
||||
if (n3) |x| _ = std.fmt.parseInt(u32, x, 10) catch return false;
|
||||
if (it.next() != null) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
pub fn classifyFileExt(filename: []const u8) FileExt {
|
||||
if (hasCExt(filename)) {
|
||||
return .c;
|
||||
|
@ -1484,26 +1688,19 @@ pub fn classifyFileExt(filename: []const u8) FileExt {
|
|||
return .assembly;
|
||||
} else if (mem.endsWith(u8, filename, ".h")) {
|
||||
return .h;
|
||||
} else if (mem.endsWith(u8, filename, ".so")) {
|
||||
return .so;
|
||||
} else if (mem.endsWith(u8, filename, ".zig")) {
|
||||
return .zig;
|
||||
} else if (mem.endsWith(u8, filename, ".zir")) {
|
||||
return .zig;
|
||||
} else if (hasSharedLibraryExt(filename)) {
|
||||
return .shared_library;
|
||||
} else if (hasStaticLibraryExt(filename)) {
|
||||
return .static_library;
|
||||
} else if (hasObjectExt(filename)) {
|
||||
return .object;
|
||||
} else {
|
||||
return .unknown;
|
||||
}
|
||||
// Look for .so.X, .so.X.Y, .so.X.Y.Z
|
||||
var it = mem.split(filename, ".");
|
||||
_ = it.next().?;
|
||||
var so_txt = it.next() orelse return .unknown;
|
||||
while (!mem.eql(u8, so_txt, "so")) {
|
||||
so_txt = it.next() orelse return .unknown;
|
||||
}
|
||||
const n1 = it.next() orelse return .unknown;
|
||||
const n2 = it.next();
|
||||
const n3 = it.next();
|
||||
|
||||
_ = std.fmt.parseInt(u32, n1, 10) catch return .unknown;
|
||||
if (n2) |x| _ = std.fmt.parseInt(u32, x, 10) catch return .unknown;
|
||||
if (n3) |x| _ = std.fmt.parseInt(u32, x, 10) catch return .unknown;
|
||||
if (it.next() != null) return .unknown;
|
||||
|
||||
return .so;
|
||||
}
|
||||
|
||||
test "classifyFileExt" {
|
||||
|
@ -1681,7 +1878,7 @@ pub fn dump_argv(argv: []const []const u8) void {
|
|||
}
|
||||
|
||||
pub fn generateBuiltinZigSource(comp: *Compilation, allocator: *Allocator) ![]u8 {
|
||||
var buffer = std.ArrayList(u8).init(comp.gpa);
|
||||
var buffer = std.ArrayList(u8).init(allocator);
|
||||
defer buffer.deinit();
|
||||
|
||||
const target = comp.getTarget();
|
||||
|
@ -1691,9 +1888,9 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: *Allocator) ![]u8
|
|||
try buffer.writer().print(
|
||||
\\usingnamespace @import("std").builtin;
|
||||
\\/// Deprecated
|
||||
\\pub const arch = std.Target.current.cpu.arch;
|
||||
\\pub const arch = Target.current.cpu.arch;
|
||||
\\/// Deprecated
|
||||
\\pub const endian = std.Target.current.cpu.arch.endian();
|
||||
\\pub const endian = Target.current.cpu.arch.endian();
|
||||
\\pub const output_mode = OutputMode.{};
|
||||
\\pub const link_mode = LinkMode.{};
|
||||
\\pub const is_test = {};
|
||||
|
|
|
@ -69,6 +69,7 @@ pub const Options = struct {
|
|||
linker_script: ?[]const u8 = null,
|
||||
version_script: ?[]const u8 = null,
|
||||
override_soname: ?[]const u8 = null,
|
||||
llvm_cpu_features: ?[*:0]const u8 = null,
|
||||
/// Extra args passed directly to LLD. Ignored when not linking with LLD.
|
||||
extra_lld_args: []const []const u8 = &[0][]const u8,
|
||||
|
||||
|
@ -134,6 +135,18 @@ pub const File = struct {
|
|||
/// rewriting it. A malicious file is detected as incremental link failure
|
||||
/// and does not cause Illegal Behavior. This operation is not atomic.
|
||||
pub fn openPath(allocator: *Allocator, options: Options) !*File {
|
||||
const use_stage1 = build_options.is_stage1 and options.use_llvm;
|
||||
if (use_stage1) {
|
||||
return switch (options.object_format) {
|
||||
.coff, .pe => &(try Coff.createEmpty(allocator, options)).base,
|
||||
.elf => &(try Elf.createEmpty(allocator, options)).base,
|
||||
.macho => &(try MachO.createEmpty(allocator, options)).base,
|
||||
.wasm => &(try Wasm.createEmpty(allocator, options)).base,
|
||||
.c => unreachable, // Reported error earlier.
|
||||
.hex => return error.HexObjectFormatUnimplemented,
|
||||
.raw => return error.RawObjectFormatUnimplemented,
|
||||
};
|
||||
}
|
||||
const use_lld = build_options.have_llvm and options.use_lld; // comptime known false when !have_llvm
|
||||
const sub_path = if (use_lld) blk: {
|
||||
if (options.module == null) {
|
||||
|
|
|
@ -1222,13 +1222,16 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
|
|||
// If there is no Zig code to compile, then we should skip flushing the output file because it
|
||||
// will not be part of the linker line anyway.
|
||||
const module_obj_path: ?[]const u8 = if (self.base.options.module) |module| blk: {
|
||||
try self.flushModule(comp);
|
||||
const use_stage1 = build_options.is_stage1 and self.base.options.use_llvm;
|
||||
if (use_stage1) {
|
||||
const obj_basename = try std.fmt.allocPrint(arena, "{}.o", .{self.base.options.root_name});
|
||||
const full_obj_path = try directory.join(arena, &[_][]const u8{obj_basename});
|
||||
break :blk full_obj_path;
|
||||
}
|
||||
|
||||
try self.flushModule(comp);
|
||||
const obj_basename = self.base.intermediary_basename.?;
|
||||
const full_obj_path = if (directory.path) |dir_path|
|
||||
try std.fs.path.join(arena, &[_][]const u8{dir_path, obj_basename})
|
||||
else
|
||||
obj_basename;
|
||||
const full_obj_path = try directory.join(arena, &[_][]const u8{obj_basename});
|
||||
break :blk full_obj_path;
|
||||
} else null;
|
||||
|
||||
|
@ -1504,7 +1507,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
|
|||
// (the check for that needs to be earlier), but they could be full paths to .so files, in which
|
||||
// case we want to avoid prepending "-l".
|
||||
const ext = Compilation.classifyFileExt(link_lib);
|
||||
const arg = if (ext == .so) link_lib else try std.fmt.allocPrint(arena, "-l{}", .{link_lib});
|
||||
const arg = if (ext == .shared_library) link_lib else try std.fmt.allocPrint(arena, "-l{}", .{link_lib});
|
||||
argv.appendAssumeCapacity(arg);
|
||||
}
|
||||
|
||||
|
|
|
@ -222,21 +222,27 @@ const usage_build_generic =
|
|||
\\ --libc [file] Provide a file which specifies libc paths
|
||||
\\
|
||||
\\Link Options:
|
||||
\\ -l[lib], --library [lib] Link against system library
|
||||
\\ -l[lib], --library [lib] Link against system library
|
||||
\\ -L[d], --library-directory [d] Add a directory to the library search path
|
||||
\\ -T[script] Use a custom linker script
|
||||
\\ --dynamic-linker [path] Set the dynamic interpreter path (usually ld.so)
|
||||
\\ --version [ver] Dynamic library semver
|
||||
\\ -rdynamic Add all symbols to the dynamic symbol table
|
||||
\\ -rpath [path] Add directory to the runtime library search path
|
||||
\\ --eh-frame-hdr Enable C++ exception handling by passing --eh-frame-hdr to linker
|
||||
\\ -dynamic Force output to be dynamically linked
|
||||
\\ -static Force output to be statically linked
|
||||
\\ -T[script] Use a custom linker script
|
||||
\\ --dynamic-linker [path] Set the dynamic interpreter path (usually ld.so)
|
||||
\\ --version [ver] Dynamic library semver
|
||||
\\ -rdynamic Add all symbols to the dynamic symbol table
|
||||
\\ -rpath [path] Add directory to the runtime library search path
|
||||
\\ --eh-frame-hdr Enable C++ exception handling by passing --eh-frame-hdr to linker
|
||||
\\ -dynamic Force output to be dynamically linked
|
||||
\\ -static Force output to be statically linked
|
||||
\\
|
||||
\\Debug Options (Zig Compiler Development):
|
||||
\\ -ftime-report Print timing diagnostics
|
||||
\\ --verbose-link Display linker invocations
|
||||
\\ --verbose-cc Display C compiler invocations
|
||||
\\ -ftime-report Print timing diagnostics
|
||||
\\ --verbose-link Display linker invocations
|
||||
\\ --verbose-cc Display C compiler invocations
|
||||
\\ --verbose-tokenize Enable compiler debug output for tokenization
|
||||
\\ --verbose-ast Enable compiler debug output for AST parsing
|
||||
\\ --verbose-ir Enable compiler debug output for Zig IR
|
||||
\\ --verbose-llvm-ir Enable compiler debug output for LLVM IR
|
||||
\\ --verbose-cimport Enable compiler debug output for C imports
|
||||
\\ --verbose-llvm-cpu-features Enable compiler debug output for LLVM CPU features
|
||||
\\
|
||||
;
|
||||
|
||||
|
@ -278,6 +284,12 @@ pub fn buildOutputType(
|
|||
var watch = false;
|
||||
var verbose_link = false;
|
||||
var verbose_cc = false;
|
||||
var verbose_tokenize = false;
|
||||
var verbose_ast = false;
|
||||
var verbose_ir = false;
|
||||
var verbose_llvm_ir = false;
|
||||
var verbose_cimport = false;
|
||||
var verbose_llvm_cpu_features = false;
|
||||
var time_report = false;
|
||||
var show_builtin = false;
|
||||
var emit_bin: Emit = .yes_default_path;
|
||||
|
@ -548,6 +560,18 @@ pub fn buildOutputType(
|
|||
verbose_link = true;
|
||||
} else if (mem.eql(u8, arg, "--verbose-cc")) {
|
||||
verbose_cc = true;
|
||||
} else if (mem.eql(u8, arg, "--verbose-tokenize")) {
|
||||
verbose_tokenize = true;
|
||||
} else if (mem.eql(u8, arg, "--verbose-ast")) {
|
||||
verbose_ast = true;
|
||||
} else if (mem.eql(u8, arg, "--verbose-ir")) {
|
||||
verbose_ir = true;
|
||||
} else if (mem.eql(u8, arg, "--verbose-llvm-ir")) {
|
||||
verbose_llvm_ir = true;
|
||||
} else if (mem.eql(u8, arg, "--verbose-cimport")) {
|
||||
verbose_cimport = true;
|
||||
} else if (mem.eql(u8, arg, "--verbose-llvm-cpu-features")) {
|
||||
verbose_llvm_cpu_features = true;
|
||||
} else if (mem.startsWith(u8, arg, "-T")) {
|
||||
linker_script = arg[2..];
|
||||
} else if (mem.startsWith(u8, arg, "-L")) {
|
||||
|
@ -563,28 +587,27 @@ pub fn buildOutputType(
|
|||
} else {
|
||||
fatal("unrecognized parameter: '{}'", .{arg});
|
||||
}
|
||||
} else if (mem.endsWith(u8, arg, ".o") or
|
||||
mem.endsWith(u8, arg, ".obj") or
|
||||
mem.endsWith(u8, arg, ".a") or
|
||||
mem.endsWith(u8, arg, ".lib"))
|
||||
{
|
||||
try link_objects.append(arg);
|
||||
} else if (Compilation.hasAsmExt(arg) or Compilation.hasCExt(arg) or Compilation.hasCppExt(arg)) {
|
||||
// TODO a way to pass extra flags on the CLI
|
||||
try c_source_files.append(.{ .src_path = arg });
|
||||
} else if (mem.endsWith(u8, arg, ".so") or
|
||||
mem.endsWith(u8, arg, ".dylib") or
|
||||
mem.endsWith(u8, arg, ".dll"))
|
||||
{
|
||||
fatal("linking against dynamic libraries not yet supported", .{});
|
||||
} else if (mem.endsWith(u8, arg, ".zig") or mem.endsWith(u8, arg, ".zir")) {
|
||||
if (root_src_file) |other| {
|
||||
fatal("found another zig file '{}' after root source file '{}'", .{ arg, other });
|
||||
} else {
|
||||
root_src_file = arg;
|
||||
}
|
||||
} else {
|
||||
fatal("unrecognized file extension of parameter '{}'", .{arg});
|
||||
} else switch (Compilation.classifyFileExt(arg)) {
|
||||
.object, .static_library => {
|
||||
try link_objects.append(arg);
|
||||
},
|
||||
.assembly, .c, .cpp, .h, .ll, .bc => {
|
||||
// TODO a way to pass extra flags on the CLI
|
||||
try c_source_files.append(.{ .src_path = arg });
|
||||
},
|
||||
.shared_library => {
|
||||
fatal("linking against dynamic libraries not yet supported", .{});
|
||||
},
|
||||
.zig, .zir => {
|
||||
if (root_src_file) |other| {
|
||||
fatal("found another zig file '{}' after root source file '{}'", .{ arg, other });
|
||||
} else {
|
||||
root_src_file = arg;
|
||||
}
|
||||
},
|
||||
.unknown => {
|
||||
fatal("unrecognized file extension of parameter '{}'", .{arg});
|
||||
},
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -617,7 +640,16 @@ pub fn buildOutputType(
|
|||
const file_ext = Compilation.classifyFileExt(mem.spanZ(it.only_arg));
|
||||
switch (file_ext) {
|
||||
.assembly, .c, .cpp, .ll, .bc, .h => try c_source_files.append(.{ .src_path = it.only_arg }),
|
||||
.unknown, .so => try link_objects.append(it.only_arg),
|
||||
.unknown, .shared_library, .object, .static_library => {
|
||||
try link_objects.append(it.only_arg);
|
||||
},
|
||||
.zig, .zir => {
|
||||
if (root_src_file) |other| {
|
||||
fatal("found another zig file '{}' after root source file '{}'", .{ it.only_arg, other });
|
||||
} else {
|
||||
root_src_file = it.only_arg;
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
.l => {
|
||||
|
@ -1173,7 +1205,15 @@ pub fn buildOutputType(
|
|||
.libc_installation = if (libc_installation) |*lci| lci else null,
|
||||
.verbose_cc = verbose_cc,
|
||||
.verbose_link = verbose_link,
|
||||
.verbose_tokenize = verbose_tokenize,
|
||||
.verbose_ast = verbose_ast,
|
||||
.verbose_ir = verbose_ir,
|
||||
.verbose_llvm_ir = verbose_llvm_ir,
|
||||
.verbose_cimport = verbose_cimport,
|
||||
.verbose_llvm_cpu_features = verbose_llvm_cpu_features,
|
||||
.machine_code_model = machine_code_model,
|
||||
.color = color,
|
||||
.time_report = time_report,
|
||||
}) catch |err| {
|
||||
fatal("unable to create compilation: {}", .{@errorName(err)});
|
||||
};
|
||||
|
@ -1193,6 +1233,10 @@ pub fn buildOutputType(
|
|||
fatal("TODO: implement `zig cc` when using it as a preprocessor", .{});
|
||||
}
|
||||
|
||||
if (build_options.is_stage1 and comp.stage1_module != null and watch) {
|
||||
std.log.warn("--watch is not recommended with the stage1 backend; it leaks memory and is not capable of incremental compilation", .{});
|
||||
}
|
||||
|
||||
const stdin = std.io.getStdIn().inStream();
|
||||
const stderr = std.io.getStdErr().outStream();
|
||||
var repl_buf: [1024]u8 = undefined;
|
||||
|
|
|
@ -10,6 +10,7 @@ const stage2 = @import("main.zig");
|
|||
const fatal = stage2.fatal;
|
||||
const CrossTarget = std.zig.CrossTarget;
|
||||
const Target = std.Target;
|
||||
const Compilation = @import("Compilation.zig");
|
||||
|
||||
comptime {
|
||||
assert(std.builtin.link_libc);
|
||||
|
@ -23,6 +24,8 @@ pub const log_level = stage2.log_level;
|
|||
pub export fn main(argc: c_int, argv: [*]const [*:0]const u8) c_int {
|
||||
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();
|
||||
|
@ -36,6 +39,106 @@ pub export fn main(argc: c_int, argv: [*]const [*:0]const u8) c_int {
|
|||
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,
|
||||
output_dir_ptr: [*]const u8,
|
||||
output_dir_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,
|
||||
link_libc: bool,
|
||||
link_libcpp: bool,
|
||||
strip: bool,
|
||||
is_single_threaded: bool,
|
||||
dll_export_fns: bool,
|
||||
link_mode_dynamic: bool,
|
||||
valgrind_enabled: bool,
|
||||
function_sections: bool,
|
||||
enable_stack_probing: bool,
|
||||
enable_time_report: bool,
|
||||
enable_stack_report: bool,
|
||||
dump_analysis: bool,
|
||||
enable_doc_generation: bool,
|
||||
emit_bin: bool,
|
||||
emit_asm: bool,
|
||||
emit_llvm_ir: 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,
|
||||
|
||||
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]);
|
||||
|
@ -199,297 +302,50 @@ export fn stage2_progress_update_node(node: *std.Progress.Node, done_count: usiz
|
|||
}
|
||||
|
||||
// ABI warning
|
||||
const Stage2Target = extern struct {
|
||||
pub const Stage2Target = extern struct {
|
||||
arch: c_int,
|
||||
vendor: c_int,
|
||||
|
||||
os: OS,
|
||||
abi: c_int,
|
||||
os: c_int,
|
||||
|
||||
is_native_os: bool,
|
||||
is_native_cpu: bool,
|
||||
|
||||
llvm_cpu_name: ?[*:0]const u8,
|
||||
llvm_cpu_features: ?[*:0]const u8,
|
||||
cpu_builtin_str: ?[*:0]const u8,
|
||||
os_builtin_str: ?[*:0]const u8,
|
||||
|
||||
dynamic_linker: ?[*:0]const u8,
|
||||
|
||||
llvm_cpu_features_asm_ptr: [*]const [*:0]const u8,
|
||||
llvm_cpu_features_asm_len: usize,
|
||||
|
||||
fn fromTarget(self: *Stage2Target, cross_target: CrossTarget) !void {
|
||||
const allocator = std.heap.c_allocator;
|
||||
|
||||
var dynamic_linker: ?[*:0]u8 = null;
|
||||
const target = try crossTargetToTarget(cross_target, &dynamic_linker);
|
||||
|
||||
const generic_arch_name = target.cpu.arch.genericName();
|
||||
var cpu_builtin_str_buffer = try std.ArrayListSentineled(u8, 0).allocPrint(allocator,
|
||||
\\Cpu{{
|
||||
\\ .arch = .{},
|
||||
\\ .model = &Target.{}.cpu.{},
|
||||
\\ .features = Target.{}.featureSet(&[_]Target.{}.Feature{{
|
||||
\\
|
||||
, .{
|
||||
@tagName(target.cpu.arch),
|
||||
generic_arch_name,
|
||||
target.cpu.model.name,
|
||||
generic_arch_name,
|
||||
generic_arch_name,
|
||||
});
|
||||
defer cpu_builtin_str_buffer.deinit();
|
||||
|
||||
var llvm_features_buffer = try std.ArrayListSentineled(u8, 0).initSize(allocator, 0);
|
||||
defer llvm_features_buffer.deinit();
|
||||
|
||||
// Unfortunately we have to do the work twice, because Clang does not support
|
||||
// the same command line parameters for CPU features when assembling code as it does
|
||||
// when compiling C code.
|
||||
var asm_features_list = std.ArrayList([*:0]const u8).init(allocator);
|
||||
defer asm_features_list.deinit();
|
||||
|
||||
for (target.cpu.arch.allFeaturesList()) |feature, index_usize| {
|
||||
const index = @intCast(Target.Cpu.Feature.Set.Index, index_usize);
|
||||
const is_enabled = target.cpu.features.isEnabled(index);
|
||||
|
||||
if (feature.llvm_name) |llvm_name| {
|
||||
const plus_or_minus = "-+"[@boolToInt(is_enabled)];
|
||||
try llvm_features_buffer.append(plus_or_minus);
|
||||
try llvm_features_buffer.appendSlice(llvm_name);
|
||||
try llvm_features_buffer.appendSlice(",");
|
||||
}
|
||||
|
||||
if (is_enabled) {
|
||||
// TODO some kind of "zig identifier escape" function rather than
|
||||
// unconditionally using @"" syntax
|
||||
try cpu_builtin_str_buffer.appendSlice(" .@\"");
|
||||
try cpu_builtin_str_buffer.appendSlice(feature.name);
|
||||
try cpu_builtin_str_buffer.appendSlice("\",\n");
|
||||
}
|
||||
}
|
||||
|
||||
switch (target.cpu.arch) {
|
||||
.riscv32, .riscv64 => {
|
||||
if (Target.riscv.featureSetHas(target.cpu.features, .relax)) {
|
||||
try asm_features_list.append("-mrelax");
|
||||
} else {
|
||||
try asm_features_list.append("-mno-relax");
|
||||
}
|
||||
},
|
||||
else => {
|
||||
// TODO
|
||||
// Argh, why doesn't the assembler accept the list of CPU features?!
|
||||
// I don't see a way to do this other than hard coding everything.
|
||||
},
|
||||
}
|
||||
|
||||
try cpu_builtin_str_buffer.appendSlice(
|
||||
\\ }),
|
||||
\\};
|
||||
\\
|
||||
);
|
||||
|
||||
assert(mem.endsWith(u8, llvm_features_buffer.span(), ","));
|
||||
llvm_features_buffer.shrink(llvm_features_buffer.len() - 1);
|
||||
|
||||
var os_builtin_str_buffer = try std.ArrayListSentineled(u8, 0).allocPrint(allocator,
|
||||
\\Os{{
|
||||
\\ .tag = .{},
|
||||
\\ .version_range = .{{
|
||||
, .{@tagName(target.os.tag)});
|
||||
defer os_builtin_str_buffer.deinit();
|
||||
|
||||
// We'll re-use the OS version range builtin string for the cache hash.
|
||||
const os_builtin_str_ver_start_index = os_builtin_str_buffer.len();
|
||||
|
||||
@setEvalBranchQuota(2000);
|
||||
switch (target.os.tag) {
|
||||
.freestanding,
|
||||
.ananas,
|
||||
.cloudabi,
|
||||
.dragonfly,
|
||||
.fuchsia,
|
||||
.ios,
|
||||
.kfreebsd,
|
||||
.lv2,
|
||||
.solaris,
|
||||
.haiku,
|
||||
.minix,
|
||||
.rtems,
|
||||
.nacl,
|
||||
.cnk,
|
||||
.aix,
|
||||
.cuda,
|
||||
.nvcl,
|
||||
.amdhsa,
|
||||
.ps4,
|
||||
.elfiamcu,
|
||||
.tvos,
|
||||
.watchos,
|
||||
.mesa3d,
|
||||
.contiki,
|
||||
.amdpal,
|
||||
.hermit,
|
||||
.hurd,
|
||||
.wasi,
|
||||
.emscripten,
|
||||
.uefi,
|
||||
.other,
|
||||
=> try os_builtin_str_buffer.appendSlice(" .none = {} }\n"),
|
||||
|
||||
.freebsd,
|
||||
.macosx,
|
||||
.netbsd,
|
||||
.openbsd,
|
||||
=> try os_builtin_str_buffer.outStream().print(
|
||||
\\ .semver = .{{
|
||||
\\ .min = .{{
|
||||
\\ .major = {},
|
||||
\\ .minor = {},
|
||||
\\ .patch = {},
|
||||
\\ }},
|
||||
\\ .max = .{{
|
||||
\\ .major = {},
|
||||
\\ .minor = {},
|
||||
\\ .patch = {},
|
||||
\\ }},
|
||||
\\ }}}},
|
||||
\\
|
||||
, .{
|
||||
target.os.version_range.semver.min.major,
|
||||
target.os.version_range.semver.min.minor,
|
||||
target.os.version_range.semver.min.patch,
|
||||
|
||||
target.os.version_range.semver.max.major,
|
||||
target.os.version_range.semver.max.minor,
|
||||
target.os.version_range.semver.max.patch,
|
||||
}),
|
||||
|
||||
.linux => try os_builtin_str_buffer.outStream().print(
|
||||
\\ .linux = .{{
|
||||
\\ .range = .{{
|
||||
\\ .min = .{{
|
||||
\\ .major = {},
|
||||
\\ .minor = {},
|
||||
\\ .patch = {},
|
||||
\\ }},
|
||||
\\ .max = .{{
|
||||
\\ .major = {},
|
||||
\\ .minor = {},
|
||||
\\ .patch = {},
|
||||
\\ }},
|
||||
\\ }},
|
||||
\\ .glibc = .{{
|
||||
\\ .major = {},
|
||||
\\ .minor = {},
|
||||
\\ .patch = {},
|
||||
\\ }},
|
||||
\\ }}}},
|
||||
\\
|
||||
, .{
|
||||
target.os.version_range.linux.range.min.major,
|
||||
target.os.version_range.linux.range.min.minor,
|
||||
target.os.version_range.linux.range.min.patch,
|
||||
|
||||
target.os.version_range.linux.range.max.major,
|
||||
target.os.version_range.linux.range.max.minor,
|
||||
target.os.version_range.linux.range.max.patch,
|
||||
|
||||
target.os.version_range.linux.glibc.major,
|
||||
target.os.version_range.linux.glibc.minor,
|
||||
target.os.version_range.linux.glibc.patch,
|
||||
}),
|
||||
|
||||
.windows => try os_builtin_str_buffer.outStream().print(
|
||||
\\ .windows = .{{
|
||||
\\ .min = {s},
|
||||
\\ .max = {s},
|
||||
\\ }}}},
|
||||
\\
|
||||
, .{
|
||||
target.os.version_range.windows.min,
|
||||
target.os.version_range.windows.max,
|
||||
}),
|
||||
}
|
||||
try os_builtin_str_buffer.appendSlice("};\n");
|
||||
|
||||
const glibc_or_darwin_version = blk: {
|
||||
if (target.isGnuLibC()) {
|
||||
const stage1_glibc = try std.heap.c_allocator.create(Stage2SemVer);
|
||||
const stage2_glibc = target.os.version_range.linux.glibc;
|
||||
stage1_glibc.* = .{
|
||||
.major = stage2_glibc.major,
|
||||
.minor = stage2_glibc.minor,
|
||||
.patch = stage2_glibc.patch,
|
||||
};
|
||||
break :blk stage1_glibc;
|
||||
} else if (target.isDarwin()) {
|
||||
const stage1_semver = try std.heap.c_allocator.create(Stage2SemVer);
|
||||
const stage2_semver = target.os.version_range.semver.min;
|
||||
stage1_semver.* = .{
|
||||
.major = stage2_semver.major,
|
||||
.minor = stage2_semver.minor,
|
||||
.patch = stage2_semver.patch,
|
||||
};
|
||||
break :blk stage1_semver;
|
||||
} else {
|
||||
break :blk null;
|
||||
}
|
||||
};
|
||||
|
||||
const std_dl = target.standardDynamicLinkerPath();
|
||||
const std_dl_z = if (std_dl.get()) |dl|
|
||||
(try mem.dupeZ(std.heap.c_allocator, u8, dl)).ptr
|
||||
else
|
||||
null;
|
||||
|
||||
const asm_features = asm_features_list.toOwnedSlice();
|
||||
self.* = .{
|
||||
.arch = @enumToInt(target.cpu.arch) + 1, // skip over ZigLLVM_UnknownArch
|
||||
.vendor = 0,
|
||||
.os = @enumToInt(target.os.tag),
|
||||
.abi = @enumToInt(target.abi),
|
||||
.llvm_cpu_name = if (target.cpu.model.llvm_name) |s| s.ptr else null,
|
||||
.llvm_cpu_features = llvm_features_buffer.toOwnedSlice().ptr,
|
||||
.llvm_cpu_features_asm_ptr = asm_features.ptr,
|
||||
.llvm_cpu_features_asm_len = asm_features.len,
|
||||
.cpu_builtin_str = cpu_builtin_str_buffer.toOwnedSlice().ptr,
|
||||
.os_builtin_str = os_builtin_str_buffer.toOwnedSlice().ptr,
|
||||
.is_native_os = cross_target.isNativeOs(),
|
||||
.is_native_cpu = cross_target.isNativeCpu(),
|
||||
.glibc_or_darwin_version = glibc_or_darwin_version,
|
||||
.dynamic_linker = dynamic_linker,
|
||||
.standard_dynamic_linker_path = std_dl_z,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
fn crossTargetToTarget(cross_target: CrossTarget, dynamic_linker_ptr: *?[*:0]u8) !Target {
|
||||
var info = try std.zig.system.NativeTargetInfo.detect(std.heap.c_allocator, cross_target);
|
||||
if (info.cpu_detection_unimplemented) {
|
||||
// TODO We want to just use detected_info.target but implementing
|
||||
// CPU model & feature detection is todo so here we rely on LLVM.
|
||||
const llvm = @import("llvm.zig");
|
||||
const llvm_cpu_name = llvm.GetHostCPUName();
|
||||
const llvm_cpu_features = llvm.GetNativeFeatures();
|
||||
const arch = Target.current.cpu.arch;
|
||||
info.target.cpu = try detectNativeCpuWithLLVM(arch, llvm_cpu_name, llvm_cpu_features);
|
||||
cross_target.updateCpuFeatures(&info.target.cpu.features);
|
||||
info.target.cpu.arch = cross_target.getCpuArch();
|
||||
}
|
||||
if (info.dynamic_linker.get()) |dl| {
|
||||
dynamic_linker_ptr.* = try mem.dupeZ(std.heap.c_allocator, u8, dl);
|
||||
} else {
|
||||
dynamic_linker_ptr.* = null;
|
||||
}
|
||||
return info.target;
|
||||
}
|
||||
|
||||
// ABI warning
|
||||
const Stage2SemVer = extern struct {
|
||||
major: u32,
|
||||
minor: u32,
|
||||
patch: u32,
|
||||
};
|
||||
|
||||
// ABI warning
|
||||
export fn stage2_cimport(stage1: *Module) [*:0]const u8 {
|
||||
@panic("TODO implement stage2_cimport");
|
||||
}
|
||||
|
||||
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 {
|
||||
return null; // no error
|
||||
}
|
||||
|
||||
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);
|
||||
// TODO integrate this with cache hash
|
||||
const file_path = path_ptr[0..path_len];
|
||||
const contents = std.fs.cwd().readFileAlloc(comp.gpa, file_path, std.math.maxInt(u32)) catch return null;
|
||||
result_len.* = contents.len;
|
||||
return contents.ptr;
|
||||
}
|
||||
|
|
|
@ -7987,7 +7987,7 @@ Error file_fetch(CodeGen *g, Buf *resolved_path, Buf *contents_buf) {
|
|||
size_t len;
|
||||
const char *contents = stage2_fetch_file(&g->stage1, buf_ptr(resolved_path), buf_len(resolved_path), &len);
|
||||
if (contents == nullptr)
|
||||
return ErrorNoMem;
|
||||
return ErrorFileNotFound;
|
||||
buf_init_from_mem(contents_buf, contents, len);
|
||||
return ErrorNone;
|
||||
}
|
||||
|
|
|
@ -8809,33 +8809,18 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
|
|||
static_assert(TargetSubsystemEfiBootServiceDriver == 5, "");
|
||||
static_assert(TargetSubsystemEfiRom == 6, "");
|
||||
static_assert(TargetSubsystemEfiRuntimeDriver == 7, "");
|
||||
{
|
||||
const char *endian_str = g->is_big_endian ? "Endian.Big" : "Endian.Little";
|
||||
buf_appendf(contents, "pub const endian = %s;\n", endian_str);
|
||||
}
|
||||
|
||||
buf_append_str(contents, "/// Deprecated: use `std.Target.current.cpu.arch`\n");
|
||||
buf_append_str(contents, "pub const arch = Target.current.cpu.arch;\n");
|
||||
buf_append_str(contents, "/// Deprecated: use `std.Target.current.cpu.arch.endian()`\n");
|
||||
buf_append_str(contents, "pub const endian = Target.current.cpu.arch.endian();\n");
|
||||
buf_appendf(contents, "pub const output_mode = OutputMode.Obj;\n");
|
||||
buf_appendf(contents, "pub const link_mode = LinkMode.Static;\n");
|
||||
buf_appendf(contents, "pub const is_test = false;\n");
|
||||
buf_appendf(contents, "pub const single_threaded = %s;\n", bool_to_str(g->is_single_threaded));
|
||||
buf_append_str(contents, "/// Deprecated: use `std.Target.cpu.arch`\n");
|
||||
buf_appendf(contents, "pub const arch = Arch.%s;\n", cur_arch);
|
||||
buf_appendf(contents, "pub const abi = Abi.%s;\n", cur_abi);
|
||||
{
|
||||
buf_append_str(contents, "pub const cpu: Cpu = ");
|
||||
if (g->zig_target->cpu_builtin_str != nullptr) {
|
||||
buf_append_str(contents, g->zig_target->cpu_builtin_str);
|
||||
} else {
|
||||
buf_appendf(contents, "Target.Cpu.baseline(.%s);\n", cur_arch);
|
||||
}
|
||||
}
|
||||
{
|
||||
buf_append_str(contents, "pub const os = ");
|
||||
if (g->zig_target->os_builtin_str != nullptr) {
|
||||
buf_append_str(contents, g->zig_target->os_builtin_str);
|
||||
} else {
|
||||
buf_appendf(contents, "Target.Os.Tag.defaultVersionRange(.%s);\n", cur_os);
|
||||
}
|
||||
}
|
||||
buf_appendf(contents, "pub const cpu: Cpu = Target.Cpu.baseline(.%s);\n", cur_arch);
|
||||
buf_appendf(contents, "pub const os = Target.Os.Tag.defaultVersionRange(.%s);\n", cur_os);
|
||||
buf_appendf(contents, "pub const object_format = ObjectFormat.%s;\n", cur_obj_fmt);
|
||||
buf_appendf(contents, "pub const mode = %s;\n", build_mode_to_str(g->build_mode));
|
||||
buf_appendf(contents, "pub const link_libc = %s;\n", bool_to_str(g->link_libc));
|
||||
|
@ -8866,6 +8851,8 @@ static Error define_builtin_compile_vars(CodeGen *g) {
|
|||
if (g->std_package == nullptr)
|
||||
return ErrorNone;
|
||||
|
||||
assert(g->main_pkg);
|
||||
|
||||
const char *builtin_zig_basename = "builtin.zig";
|
||||
|
||||
Buf *contents;
|
||||
|
@ -8879,17 +8866,22 @@ static Error define_builtin_compile_vars(CodeGen *g) {
|
|||
fprintf(stderr, "Unable to write file '%s': %s\n", buf_ptr(g->builtin_zig_path), err_str(err));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
g->compile_var_package = new_package(buf_ptr(g->output_dir), builtin_zig_basename, "builtin");
|
||||
} else {
|
||||
Buf *resolve_paths[] = { g->builtin_zig_path, };
|
||||
*g->builtin_zig_path = os_path_resolve(resolve_paths, 1);
|
||||
|
||||
contents = buf_alloc();
|
||||
if ((err = os_fetch_file_path(g->builtin_zig_path, contents))) {
|
||||
fprintf(stderr, "unable to open '%s': %s\n", buf_ptr(g->builtin_zig_path), err_str(err));
|
||||
exit(1);
|
||||
}
|
||||
Buf builtin_dirname = BUF_INIT;
|
||||
os_path_dirname(g->builtin_zig_path, &builtin_dirname);
|
||||
g->compile_var_package = new_package(buf_ptr(&builtin_dirname), builtin_zig_basename, "builtin");
|
||||
}
|
||||
|
||||
assert(g->main_pkg);
|
||||
assert(g->std_package);
|
||||
g->compile_var_package = new_package(buf_ptr(g->output_dir), builtin_zig_basename, "builtin");
|
||||
if (g->is_test_build) {
|
||||
if (g->test_runner_package == nullptr) {
|
||||
g->test_runner_package = create_test_runner_pkg(g);
|
||||
|
@ -8914,6 +8906,13 @@ static void init(CodeGen *g) {
|
|||
if (g->module)
|
||||
return;
|
||||
|
||||
codegen_add_time_event(g, "Initialize");
|
||||
{
|
||||
const char *progress_name = "Initialize";
|
||||
codegen_switch_sub_prog_node(g, stage2_progress_start(g->main_progress_node,
|
||||
progress_name, strlen(progress_name), 0));
|
||||
}
|
||||
|
||||
g->have_err_ret_tracing = detect_err_ret_tracing(g);
|
||||
|
||||
assert(g->root_out_name);
|
||||
|
@ -9374,19 +9373,11 @@ void codegen_destroy(CodeGen *g) {
|
|||
|
||||
CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget *target,
|
||||
BuildMode build_mode, Buf *override_lib_dir,
|
||||
bool is_test_build, Stage2ProgressNode *progress_node)
|
||||
bool is_test_build)
|
||||
{
|
||||
CodeGen *g = heap::c_allocator.create<CodeGen>();
|
||||
g->emit_bin = true;
|
||||
g->pass1_arena = heap::ArenaAllocator::construct(&heap::c_allocator, &heap::c_allocator, "pass1");
|
||||
g->main_progress_node = progress_node;
|
||||
|
||||
codegen_add_time_event(g, "Initialize");
|
||||
{
|
||||
const char *progress_name = "Initialize";
|
||||
codegen_switch_sub_prog_node(g, stage2_progress_start(g->main_progress_node,
|
||||
progress_name, strlen(progress_name), 0));
|
||||
}
|
||||
|
||||
g->subsystem = TargetSubsystemAuto;
|
||||
g->zig_target = target;
|
||||
|
@ -9440,7 +9431,7 @@ CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget
|
|||
Buf resolved_main_pkg_path = os_path_resolve(&main_pkg_path, 1);
|
||||
|
||||
if (!buf_starts_with_buf(&resolved_root_src_path, &resolved_main_pkg_path)) {
|
||||
fprintf(stderr, "Root source path '%s' outside main package path '%s'",
|
||||
fprintf(stderr, "Root source path '%s' outside main package path '%s'\n",
|
||||
buf_ptr(root_src_path), buf_ptr(main_pkg_path));
|
||||
exit(1);
|
||||
}
|
||||
|
|
|
@ -16,8 +16,7 @@
|
|||
#include <stdio.h>
|
||||
|
||||
CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget *target,
|
||||
BuildMode build_mode, Buf *zig_lib_dir,
|
||||
bool is_test_build, Stage2ProgressNode *progress_node);
|
||||
BuildMode build_mode, Buf *zig_lib_dir, bool is_test_build);
|
||||
|
||||
void codegen_build_object(CodeGen *g);
|
||||
void codegen_destroy(CodeGen *);
|
||||
|
|
|
@ -20,13 +20,14 @@ struct ZigStage1 *zig_stage1_create(BuildMode optimize_mode,
|
|||
const char *main_pkg_path_ptr, size_t main_pkg_path_len,
|
||||
const char *root_src_path_ptr, size_t root_src_path_len,
|
||||
const char *zig_lib_dir_ptr, size_t zig_lib_dir_len,
|
||||
const ZigTarget *target, bool is_test_build, Stage2ProgressNode *progress_node)
|
||||
const ZigTarget *target, bool is_test_build)
|
||||
{
|
||||
Buf *main_pkg_path = buf_create_from_mem(main_pkg_path_ptr, main_pkg_path_len);
|
||||
Buf *main_pkg_path = (main_pkg_path_len == 0) ?
|
||||
nullptr : buf_create_from_mem(main_pkg_path_ptr, main_pkg_path_len);
|
||||
Buf *root_src_path = buf_create_from_mem(root_src_path_ptr, root_src_path_len);
|
||||
Buf *zig_lib_dir = buf_create_from_mem(zig_lib_dir_ptr, zig_lib_dir_len);
|
||||
CodeGen *g = codegen_create(main_pkg_path, root_src_path, target, optimize_mode,
|
||||
zig_lib_dir, is_test_build, progress_node);
|
||||
zig_lib_dir, is_test_build);
|
||||
return &g->stage1;
|
||||
}
|
||||
|
||||
|
@ -68,8 +69,6 @@ void zig_stage1_build_object(struct ZigStage1 *stage1) {
|
|||
CodeGen *g = reinterpret_cast<CodeGen *>(stage1);
|
||||
|
||||
g->root_out_name = buf_create_from_mem(stage1->root_name_ptr, stage1->root_name_len);
|
||||
g->zig_lib_dir = buf_create_from_mem(stage1->zig_lib_dir_ptr, stage1->zig_lib_dir_len);
|
||||
g->zig_std_dir = buf_create_from_mem(stage1->zig_std_dir_ptr, stage1->zig_std_dir_len);
|
||||
g->output_dir = buf_create_from_mem(stage1->output_dir_ptr, stage1->output_dir_len);
|
||||
if (stage1->builtin_zig_path_len != 0) {
|
||||
g->builtin_zig_path = buf_create_from_mem(stage1->builtin_zig_path_ptr, stage1->builtin_zig_path_len);
|
||||
|
@ -119,6 +118,8 @@ void zig_stage1_build_object(struct ZigStage1 *stage1) {
|
|||
}
|
||||
}
|
||||
|
||||
g->main_progress_node = stage1->main_progress_node;
|
||||
|
||||
add_package(g, stage1->root_pkg, g->main_pkg);
|
||||
|
||||
codegen_build_object(g);
|
||||
|
|
25
src/stage1.h
25
src/stage1.h
|
@ -100,22 +100,14 @@ enum Os {
|
|||
// ABI warning
|
||||
struct ZigTarget {
|
||||
enum ZigLLVM_ArchType arch;
|
||||
enum ZigLLVM_VendorType vendor;
|
||||
|
||||
enum Os os;
|
||||
enum ZigLLVM_EnvironmentType abi;
|
||||
Os os;
|
||||
|
||||
bool is_native_os;
|
||||
bool is_native_cpu;
|
||||
|
||||
const char *llvm_cpu_name;
|
||||
const char *llvm_cpu_features;
|
||||
const char *cpu_builtin_str;
|
||||
const char *os_builtin_str;
|
||||
const char *dynamic_linker;
|
||||
|
||||
const char **llvm_cpu_features_asm_ptr;
|
||||
size_t llvm_cpu_features_asm_len;
|
||||
};
|
||||
|
||||
// ABI warning
|
||||
|
@ -161,18 +153,13 @@ struct ZigStage1 {
|
|||
const char *test_name_prefix_ptr;
|
||||
size_t test_name_prefix_len;
|
||||
|
||||
const char *zig_lib_dir_ptr;
|
||||
size_t zig_lib_dir_len;
|
||||
|
||||
const char *zig_std_dir_ptr;
|
||||
size_t zig_std_dir_len;
|
||||
|
||||
void *userdata;
|
||||
struct ZigStage1Pkg *root_pkg;
|
||||
struct Stage2ProgressNode *main_progress_node;
|
||||
|
||||
CodeModel code_model;
|
||||
TargetSubsystem subsystem;
|
||||
ErrColor err_color;
|
||||
enum CodeModel code_model;
|
||||
enum TargetSubsystem subsystem;
|
||||
enum ErrColor err_color;
|
||||
|
||||
bool pic;
|
||||
bool link_libc;
|
||||
|
@ -206,7 +193,7 @@ ZIG_EXTERN_C struct ZigStage1 *zig_stage1_create(enum BuildMode optimize_mode,
|
|||
const char *main_pkg_path_ptr, size_t main_pkg_path_len,
|
||||
const char *root_src_path_ptr, size_t root_src_path_len,
|
||||
const char *zig_lib_dir_ptr, size_t zig_lib_dir_len,
|
||||
const ZigTarget *target, bool is_test_build, Stage2ProgressNode *progress_node);
|
||||
const struct ZigTarget *target, bool is_test_build);
|
||||
|
||||
ZIG_EXTERN_C void zig_stage1_build_object(struct ZigStage1 *);
|
||||
|
||||
|
|
241
src/stage2.cpp
241
src/stage2.cpp
|
@ -1,241 +0,0 @@
|
|||
// This file is a shim for zig1. The real implementations of these are in
|
||||
// src-self-hosted/stage1.zig
|
||||
|
||||
#include "stage2.h"
|
||||
#include "util.hpp"
|
||||
#include "zig_llvm.h"
|
||||
#include "target.hpp"
|
||||
#include "buffer.hpp"
|
||||
#include "os.hpp"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
void stage2_panic(const char *ptr, size_t len) {
|
||||
fwrite(ptr, 1, len, stderr);
|
||||
fprintf(stderr, "\n");
|
||||
fflush(stderr);
|
||||
abort();
|
||||
}
|
||||
|
||||
struct Stage2Progress {
|
||||
int trash;
|
||||
};
|
||||
|
||||
struct Stage2ProgressNode {
|
||||
int trash;
|
||||
};
|
||||
|
||||
Stage2Progress *stage2_progress_create(void) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void stage2_progress_destroy(Stage2Progress *progress) {}
|
||||
|
||||
Stage2ProgressNode *stage2_progress_start_root(Stage2Progress *progress,
|
||||
const char *name_ptr, size_t name_len, size_t estimated_total_items)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
Stage2ProgressNode *stage2_progress_start(Stage2ProgressNode *node,
|
||||
const char *name_ptr, size_t name_len, size_t estimated_total_items)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
void stage2_progress_end(Stage2ProgressNode *node) {}
|
||||
void stage2_progress_complete_one(Stage2ProgressNode *node) {}
|
||||
void stage2_progress_disable_tty(Stage2Progress *progress) {}
|
||||
void stage2_progress_update_node(Stage2ProgressNode *node, size_t completed_count, size_t estimated_total_items){}
|
||||
|
||||
static Os get_zig_os_type(ZigLLVM_OSType os_type) {
|
||||
switch (os_type) {
|
||||
case ZigLLVM_UnknownOS:
|
||||
return OsFreestanding;
|
||||
case ZigLLVM_Ananas:
|
||||
return OsAnanas;
|
||||
case ZigLLVM_CloudABI:
|
||||
return OsCloudABI;
|
||||
case ZigLLVM_DragonFly:
|
||||
return OsDragonFly;
|
||||
case ZigLLVM_FreeBSD:
|
||||
return OsFreeBSD;
|
||||
case ZigLLVM_Fuchsia:
|
||||
return OsFuchsia;
|
||||
case ZigLLVM_IOS:
|
||||
return OsIOS;
|
||||
case ZigLLVM_KFreeBSD:
|
||||
return OsKFreeBSD;
|
||||
case ZigLLVM_Linux:
|
||||
return OsLinux;
|
||||
case ZigLLVM_Lv2:
|
||||
return OsLv2;
|
||||
case ZigLLVM_Darwin:
|
||||
case ZigLLVM_MacOSX:
|
||||
return OsMacOSX;
|
||||
case ZigLLVM_NetBSD:
|
||||
return OsNetBSD;
|
||||
case ZigLLVM_OpenBSD:
|
||||
return OsOpenBSD;
|
||||
case ZigLLVM_Solaris:
|
||||
return OsSolaris;
|
||||
case ZigLLVM_Win32:
|
||||
return OsWindows;
|
||||
case ZigLLVM_Haiku:
|
||||
return OsHaiku;
|
||||
case ZigLLVM_Minix:
|
||||
return OsMinix;
|
||||
case ZigLLVM_RTEMS:
|
||||
return OsRTEMS;
|
||||
case ZigLLVM_NaCl:
|
||||
return OsNaCl;
|
||||
case ZigLLVM_CNK:
|
||||
return OsCNK;
|
||||
case ZigLLVM_AIX:
|
||||
return OsAIX;
|
||||
case ZigLLVM_CUDA:
|
||||
return OsCUDA;
|
||||
case ZigLLVM_NVCL:
|
||||
return OsNVCL;
|
||||
case ZigLLVM_AMDHSA:
|
||||
return OsAMDHSA;
|
||||
case ZigLLVM_PS4:
|
||||
return OsPS4;
|
||||
case ZigLLVM_ELFIAMCU:
|
||||
return OsELFIAMCU;
|
||||
case ZigLLVM_TvOS:
|
||||
return OsTvOS;
|
||||
case ZigLLVM_WatchOS:
|
||||
return OsWatchOS;
|
||||
case ZigLLVM_Mesa3D:
|
||||
return OsMesa3D;
|
||||
case ZigLLVM_Contiki:
|
||||
return OsContiki;
|
||||
case ZigLLVM_AMDPAL:
|
||||
return OsAMDPAL;
|
||||
case ZigLLVM_HermitCore:
|
||||
return OsHermitCore;
|
||||
case ZigLLVM_Hurd:
|
||||
return OsHurd;
|
||||
case ZigLLVM_WASI:
|
||||
return OsWASI;
|
||||
case ZigLLVM_Emscripten:
|
||||
return OsEmscripten;
|
||||
}
|
||||
zig_unreachable();
|
||||
}
|
||||
|
||||
static void get_native_target(ZigTarget *target) {
|
||||
// first zero initialize
|
||||
*target = {};
|
||||
|
||||
ZigLLVM_OSType os_type;
|
||||
ZigLLVM_ObjectFormatType oformat; // ignored; based on arch/os
|
||||
ZigLLVMGetNativeTarget(
|
||||
&target->arch,
|
||||
&target->vendor,
|
||||
&os_type,
|
||||
&target->abi,
|
||||
&oformat);
|
||||
target->os = get_zig_os_type(os_type);
|
||||
target->is_native_os = true;
|
||||
target->is_native_cpu = true;
|
||||
if (target->abi == ZigLLVM_UnknownEnvironment) {
|
||||
target->abi = target_default_abi(target->arch, target->os);
|
||||
}
|
||||
}
|
||||
|
||||
Error stage2_target_parse(struct ZigTarget *target, const char *zig_triple, const char *mcpu,
|
||||
const char *dynamic_linker)
|
||||
{
|
||||
Error err;
|
||||
|
||||
if (zig_triple != nullptr && strcmp(zig_triple, "native") == 0) {
|
||||
zig_triple = nullptr;
|
||||
}
|
||||
|
||||
if (zig_triple == nullptr) {
|
||||
get_native_target(target);
|
||||
|
||||
if (mcpu == nullptr) {
|
||||
target->llvm_cpu_name = ZigLLVMGetHostCPUName();
|
||||
target->llvm_cpu_features = ZigLLVMGetNativeFeatures();
|
||||
} else if (strcmp(mcpu, "baseline") == 0) {
|
||||
target->is_native_os = false;
|
||||
target->is_native_cpu = false;
|
||||
target->llvm_cpu_name = "";
|
||||
target->llvm_cpu_features = "";
|
||||
} else {
|
||||
const char *msg = "stage0 can't handle CPU/features in the target";
|
||||
stage2_panic(msg, strlen(msg));
|
||||
}
|
||||
} else {
|
||||
// first initialize all to zero
|
||||
*target = {};
|
||||
|
||||
SplitIterator it = memSplit(str(zig_triple), str("-"));
|
||||
|
||||
Optional<Slice<uint8_t>> opt_archsub = SplitIterator_next(&it);
|
||||
Optional<Slice<uint8_t>> opt_os = SplitIterator_next(&it);
|
||||
Optional<Slice<uint8_t>> opt_abi = SplitIterator_next(&it);
|
||||
|
||||
if (!opt_archsub.is_some)
|
||||
return ErrorMissingArchitecture;
|
||||
|
||||
if ((err = target_parse_arch(&target->arch, (char*)opt_archsub.value.ptr, opt_archsub.value.len))) {
|
||||
return err;
|
||||
}
|
||||
|
||||
if (!opt_os.is_some)
|
||||
return ErrorMissingOperatingSystem;
|
||||
|
||||
if ((err = target_parse_os(&target->os, (char*)opt_os.value.ptr, opt_os.value.len))) {
|
||||
return err;
|
||||
}
|
||||
|
||||
if (opt_abi.is_some) {
|
||||
if ((err = target_parse_abi(&target->abi, (char*)opt_abi.value.ptr, opt_abi.value.len))) {
|
||||
return err;
|
||||
}
|
||||
} else {
|
||||
target->abi = target_default_abi(target->arch, target->os);
|
||||
}
|
||||
|
||||
if (mcpu != nullptr && strcmp(mcpu, "baseline") != 0) {
|
||||
const char *msg = "stage0 can't handle CPU/features in the target";
|
||||
stage2_panic(msg, strlen(msg));
|
||||
}
|
||||
}
|
||||
|
||||
if (dynamic_linker != nullptr) {
|
||||
target->dynamic_linker = dynamic_linker;
|
||||
}
|
||||
|
||||
return ErrorNone;
|
||||
}
|
||||
|
||||
const char *stage2_fetch_file(struct ZigStage1 *stage1, const char *path_ptr, size_t path_len,
|
||||
size_t *result_len)
|
||||
{
|
||||
Error err;
|
||||
Buf contents_buf = BUF_INIT;
|
||||
Buf path_buf = BUF_INIT;
|
||||
|
||||
buf_init_from_mem(&path_buf, path_ptr, path_len);
|
||||
if ((err = os_fetch_file_path(&path_buf, &contents_buf))) {
|
||||
return nullptr;
|
||||
}
|
||||
*result_len = buf_len(&contents_buf);
|
||||
return buf_ptr(&contents_buf);
|
||||
}
|
||||
|
||||
const char *stage2_cimport(struct ZigStage1 *stage1) {
|
||||
const char *msg = "stage0 called stage2_cimport";
|
||||
stage2_panic(msg, strlen(msg));
|
||||
}
|
||||
|
||||
const char *stage2_add_link_lib(struct ZigStage1 *stage1,
|
||||
const char *lib_name_ptr, size_t lib_name_len,
|
||||
const char *symbol_name_ptr, size_t symbol_name_len)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
16
src/stage2.h
16
src/stage2.h
|
@ -130,23 +130,23 @@ struct Stage2ErrorMsg {
|
|||
ZIG_EXTERN_C ZIG_ATTRIBUTE_NORETURN void stage2_panic(const char *ptr, size_t len);
|
||||
|
||||
// ABI warning
|
||||
ZIG_EXTERN_C Stage2Progress *stage2_progress_create(void);
|
||||
ZIG_EXTERN_C struct Stage2Progress *stage2_progress_create(void);
|
||||
// ABI warning
|
||||
ZIG_EXTERN_C void stage2_progress_disable_tty(Stage2Progress *progress);
|
||||
ZIG_EXTERN_C void stage2_progress_disable_tty(struct Stage2Progress *progress);
|
||||
// ABI warning
|
||||
ZIG_EXTERN_C void stage2_progress_destroy(Stage2Progress *progress);
|
||||
ZIG_EXTERN_C void stage2_progress_destroy(struct Stage2Progress *progress);
|
||||
// ABI warning
|
||||
ZIG_EXTERN_C Stage2ProgressNode *stage2_progress_start_root(Stage2Progress *progress,
|
||||
ZIG_EXTERN_C struct Stage2ProgressNode *stage2_progress_start_root(struct Stage2Progress *progress,
|
||||
const char *name_ptr, size_t name_len, size_t estimated_total_items);
|
||||
// ABI warning
|
||||
ZIG_EXTERN_C Stage2ProgressNode *stage2_progress_start(Stage2ProgressNode *node,
|
||||
ZIG_EXTERN_C struct Stage2ProgressNode *stage2_progress_start(struct Stage2ProgressNode *node,
|
||||
const char *name_ptr, size_t name_len, size_t estimated_total_items);
|
||||
// ABI warning
|
||||
ZIG_EXTERN_C void stage2_progress_end(Stage2ProgressNode *node);
|
||||
ZIG_EXTERN_C void stage2_progress_end(struct Stage2ProgressNode *node);
|
||||
// ABI warning
|
||||
ZIG_EXTERN_C void stage2_progress_complete_one(Stage2ProgressNode *node);
|
||||
ZIG_EXTERN_C void stage2_progress_complete_one(struct Stage2ProgressNode *node);
|
||||
// ABI warning
|
||||
ZIG_EXTERN_C void stage2_progress_update_node(Stage2ProgressNode *node,
|
||||
ZIG_EXTERN_C void stage2_progress_update_node(struct Stage2ProgressNode *node,
|
||||
size_t completed_count, size_t estimated_total_items);
|
||||
|
||||
// ABI warning
|
||||
|
|
|
@ -380,10 +380,6 @@ Error target_parse_abi(ZigLLVM_EnvironmentType *out_abi, const char *abi_ptr, si
|
|||
return ErrorUnknownABI;
|
||||
}
|
||||
|
||||
Error target_parse_triple(ZigTarget *target, const char *triple, const char *mcpu, const char *dynamic_linker) {
|
||||
return stage2_target_parse(target, triple, mcpu, dynamic_linker);
|
||||
}
|
||||
|
||||
const char *target_arch_name(ZigLLVM_ArchType arch) {
|
||||
return ZigLLVMGetArchTypeName(arch);
|
||||
}
|
||||
|
@ -408,7 +404,7 @@ void target_triple_llvm(Buf *triple, const ZigTarget *target) {
|
|||
buf_resize(triple, 0);
|
||||
buf_appendf(triple, "%s-%s-%s-%s",
|
||||
ZigLLVMGetArchTypeName(target->arch),
|
||||
ZigLLVMGetVendorTypeName(target->vendor),
|
||||
ZigLLVMGetVendorTypeName(ZigLLVM_UnknownVendor),
|
||||
ZigLLVMGetOSTypeName(get_llvm_os_type(target->os)),
|
||||
ZigLLVMGetEnvironmentTypeName(target->abi));
|
||||
}
|
||||
|
@ -1149,7 +1145,6 @@ void target_libc_enum(size_t index, ZigTarget *out_target) {
|
|||
out_target->arch = libcs_available[index].arch;
|
||||
out_target->os = libcs_available[index].os;
|
||||
out_target->abi = libcs_available[index].abi;
|
||||
out_target->vendor = ZigLLVM_UnknownVendor;
|
||||
out_target->is_native_os = false;
|
||||
out_target->is_native_cpu = false;
|
||||
}
|
||||
|
|
|
@ -25,7 +25,6 @@ enum CIntType {
|
|||
CIntTypeCount,
|
||||
};
|
||||
|
||||
Error target_parse_triple(ZigTarget *target, const char *triple, const char *mcpu, const char *dynamic_linker);
|
||||
Error target_parse_arch(ZigLLVM_ArchType *arch, const char *arch_ptr, size_t arch_len);
|
||||
Error target_parse_os(Os *os, const char *os_ptr, size_t os_len);
|
||||
Error target_parse_abi(ZigLLVM_EnvironmentType *abi, const char *abi_ptr, size_t abi_len);
|
||||
|
|
251
src/zig0.cpp
251
src/zig0.cpp
|
@ -14,6 +14,9 @@
|
|||
#include "stage2.h"
|
||||
#include "target.hpp"
|
||||
#include "error.hpp"
|
||||
#include "util.hpp"
|
||||
#include "buffer.hpp"
|
||||
#include "os.hpp"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
@ -33,7 +36,6 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {
|
|||
" --output-dir [dir] override output directory (defaults to cwd)\n"
|
||||
" --pkg-begin [name] [path] make pkg available to import and push current pkg\n"
|
||||
" --pkg-end pop current pkg\n"
|
||||
" --main-pkg-path set the directory of the root package\n"
|
||||
" --release-fast build with optimizations on and safety off\n"
|
||||
" --release-safe build with optimizations on and safety on\n"
|
||||
" --release-small build with size optimizations on and safety off\n"
|
||||
|
@ -53,6 +55,170 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {
|
|||
return return_code;
|
||||
}
|
||||
|
||||
static Os get_zig_os_type(ZigLLVM_OSType os_type) {
|
||||
switch (os_type) {
|
||||
case ZigLLVM_UnknownOS:
|
||||
return OsFreestanding;
|
||||
case ZigLLVM_Ananas:
|
||||
return OsAnanas;
|
||||
case ZigLLVM_CloudABI:
|
||||
return OsCloudABI;
|
||||
case ZigLLVM_DragonFly:
|
||||
return OsDragonFly;
|
||||
case ZigLLVM_FreeBSD:
|
||||
return OsFreeBSD;
|
||||
case ZigLLVM_Fuchsia:
|
||||
return OsFuchsia;
|
||||
case ZigLLVM_IOS:
|
||||
return OsIOS;
|
||||
case ZigLLVM_KFreeBSD:
|
||||
return OsKFreeBSD;
|
||||
case ZigLLVM_Linux:
|
||||
return OsLinux;
|
||||
case ZigLLVM_Lv2:
|
||||
return OsLv2;
|
||||
case ZigLLVM_Darwin:
|
||||
case ZigLLVM_MacOSX:
|
||||
return OsMacOSX;
|
||||
case ZigLLVM_NetBSD:
|
||||
return OsNetBSD;
|
||||
case ZigLLVM_OpenBSD:
|
||||
return OsOpenBSD;
|
||||
case ZigLLVM_Solaris:
|
||||
return OsSolaris;
|
||||
case ZigLLVM_Win32:
|
||||
return OsWindows;
|
||||
case ZigLLVM_Haiku:
|
||||
return OsHaiku;
|
||||
case ZigLLVM_Minix:
|
||||
return OsMinix;
|
||||
case ZigLLVM_RTEMS:
|
||||
return OsRTEMS;
|
||||
case ZigLLVM_NaCl:
|
||||
return OsNaCl;
|
||||
case ZigLLVM_CNK:
|
||||
return OsCNK;
|
||||
case ZigLLVM_AIX:
|
||||
return OsAIX;
|
||||
case ZigLLVM_CUDA:
|
||||
return OsCUDA;
|
||||
case ZigLLVM_NVCL:
|
||||
return OsNVCL;
|
||||
case ZigLLVM_AMDHSA:
|
||||
return OsAMDHSA;
|
||||
case ZigLLVM_PS4:
|
||||
return OsPS4;
|
||||
case ZigLLVM_ELFIAMCU:
|
||||
return OsELFIAMCU;
|
||||
case ZigLLVM_TvOS:
|
||||
return OsTvOS;
|
||||
case ZigLLVM_WatchOS:
|
||||
return OsWatchOS;
|
||||
case ZigLLVM_Mesa3D:
|
||||
return OsMesa3D;
|
||||
case ZigLLVM_Contiki:
|
||||
return OsContiki;
|
||||
case ZigLLVM_AMDPAL:
|
||||
return OsAMDPAL;
|
||||
case ZigLLVM_HermitCore:
|
||||
return OsHermitCore;
|
||||
case ZigLLVM_Hurd:
|
||||
return OsHurd;
|
||||
case ZigLLVM_WASI:
|
||||
return OsWASI;
|
||||
case ZigLLVM_Emscripten:
|
||||
return OsEmscripten;
|
||||
}
|
||||
zig_unreachable();
|
||||
}
|
||||
|
||||
static void get_native_target(ZigTarget *target) {
|
||||
// first zero initialize
|
||||
*target = {};
|
||||
|
||||
ZigLLVM_OSType os_type;
|
||||
ZigLLVM_ObjectFormatType oformat; // ignored; based on arch/os
|
||||
ZigLLVM_VendorType trash;
|
||||
ZigLLVMGetNativeTarget(
|
||||
&target->arch,
|
||||
&trash,
|
||||
&os_type,
|
||||
&target->abi,
|
||||
&oformat);
|
||||
target->os = get_zig_os_type(os_type);
|
||||
target->is_native_os = true;
|
||||
target->is_native_cpu = true;
|
||||
if (target->abi == ZigLLVM_UnknownEnvironment) {
|
||||
target->abi = target_default_abi(target->arch, target->os);
|
||||
}
|
||||
}
|
||||
|
||||
static Error target_parse_triple(struct ZigTarget *target, const char *zig_triple, const char *mcpu,
|
||||
const char *dynamic_linker)
|
||||
{
|
||||
Error err;
|
||||
|
||||
if (zig_triple != nullptr && strcmp(zig_triple, "native") == 0) {
|
||||
zig_triple = nullptr;
|
||||
}
|
||||
|
||||
if (zig_triple == nullptr) {
|
||||
get_native_target(target);
|
||||
|
||||
if (mcpu == nullptr) {
|
||||
target->llvm_cpu_name = ZigLLVMGetHostCPUName();
|
||||
target->llvm_cpu_features = ZigLLVMGetNativeFeatures();
|
||||
} else if (strcmp(mcpu, "baseline") == 0) {
|
||||
target->is_native_os = false;
|
||||
target->is_native_cpu = false;
|
||||
target->llvm_cpu_name = "";
|
||||
target->llvm_cpu_features = "";
|
||||
} else {
|
||||
const char *msg = "stage0 can't handle CPU/features in the target";
|
||||
stage2_panic(msg, strlen(msg));
|
||||
}
|
||||
} else {
|
||||
// first initialize all to zero
|
||||
*target = {};
|
||||
|
||||
SplitIterator it = memSplit(str(zig_triple), str("-"));
|
||||
|
||||
Optional<Slice<uint8_t>> opt_archsub = SplitIterator_next(&it);
|
||||
Optional<Slice<uint8_t>> opt_os = SplitIterator_next(&it);
|
||||
Optional<Slice<uint8_t>> opt_abi = SplitIterator_next(&it);
|
||||
|
||||
if (!opt_archsub.is_some)
|
||||
return ErrorMissingArchitecture;
|
||||
|
||||
if ((err = target_parse_arch(&target->arch, (char*)opt_archsub.value.ptr, opt_archsub.value.len))) {
|
||||
return err;
|
||||
}
|
||||
|
||||
if (!opt_os.is_some)
|
||||
return ErrorMissingOperatingSystem;
|
||||
|
||||
if ((err = target_parse_os(&target->os, (char*)opt_os.value.ptr, opt_os.value.len))) {
|
||||
return err;
|
||||
}
|
||||
|
||||
if (opt_abi.is_some) {
|
||||
if ((err = target_parse_abi(&target->abi, (char*)opt_abi.value.ptr, opt_abi.value.len))) {
|
||||
return err;
|
||||
}
|
||||
} else {
|
||||
target->abi = target_default_abi(target->arch, target->os);
|
||||
}
|
||||
|
||||
if (mcpu != nullptr && strcmp(mcpu, "baseline") != 0) {
|
||||
const char *msg = "stage0 can't handle CPU/features in the target";
|
||||
stage2_panic(msg, strlen(msg));
|
||||
}
|
||||
}
|
||||
|
||||
return ErrorNone;
|
||||
}
|
||||
|
||||
|
||||
static bool str_starts_with(const char *s1, const char *s2) {
|
||||
size_t s2_len = strlen(s2);
|
||||
if (strlen(s1) < s2_len) {
|
||||
|
@ -90,10 +256,9 @@ int main(int argc, char **argv) {
|
|||
bool link_libcpp = false;
|
||||
const char *target_string = nullptr;
|
||||
ZigStage1Pkg *cur_pkg = heap::c_allocator.create<ZigStage1Pkg>();
|
||||
BuildMode build_mode = BuildModeDebug;
|
||||
BuildMode optimize_mode = BuildModeDebug;
|
||||
TargetSubsystem subsystem = TargetSubsystemAuto;
|
||||
const char *override_lib_dir = nullptr;
|
||||
const char *main_pkg_path = nullptr;
|
||||
const char *mcpu = nullptr;
|
||||
|
||||
for (int i = 1; i < argc; i += 1) {
|
||||
|
@ -103,11 +268,11 @@ int main(int argc, char **argv) {
|
|||
if (strcmp(arg, "--") == 0) {
|
||||
fprintf(stderr, "Unexpected end-of-parameter mark: %s\n", arg);
|
||||
} else if (strcmp(arg, "--release-fast") == 0) {
|
||||
build_mode = BuildModeFastRelease;
|
||||
optimize_mode = BuildModeFastRelease;
|
||||
} else if (strcmp(arg, "--release-safe") == 0) {
|
||||
build_mode = BuildModeSafeRelease;
|
||||
optimize_mode = BuildModeSafeRelease;
|
||||
} else if (strcmp(arg, "--release-small") == 0) {
|
||||
build_mode = BuildModeSmallRelease;
|
||||
optimize_mode = BuildModeSmallRelease;
|
||||
} else if (strcmp(arg, "--help") == 0) {
|
||||
return print_full_usage(arg0, stdout, EXIT_SUCCESS);
|
||||
} else if (strcmp(arg, "--strip") == 0) {
|
||||
|
@ -183,8 +348,6 @@ int main(int argc, char **argv) {
|
|||
dynamic_linker = argv[i];
|
||||
} else if (strcmp(arg, "--override-lib-dir") == 0) {
|
||||
override_lib_dir = argv[i];
|
||||
} else if (strcmp(arg, "--main-pkg-path") == 0) {
|
||||
main_pkg_path = argv[i];
|
||||
} else if (strcmp(arg, "--library") == 0 || strcmp(arg, "-l") == 0) {
|
||||
if (strcmp(argv[i], "c") == 0) {
|
||||
link_libc = true;
|
||||
|
@ -264,12 +427,13 @@ int main(int argc, char **argv) {
|
|||
return print_error_usage(arg0);
|
||||
}
|
||||
|
||||
ZigStage1 *stage1 = zig_stage1_create(build_mode,
|
||||
main_pkg_path, (main_pkg_path == nullptr) ? 0 : strlen(main_pkg_path),
|
||||
ZigStage1 *stage1 = zig_stage1_create(optimize_mode,
|
||||
nullptr, 0,
|
||||
in_file, strlen(in_file),
|
||||
override_lib_dir, strlen(override_lib_dir), &target, false,
|
||||
root_progress_node);
|
||||
override_lib_dir, strlen(override_lib_dir),
|
||||
&target, false);
|
||||
|
||||
stage1->main_progress_node = root_progress_node;
|
||||
stage1->root_name_ptr = out_name;
|
||||
stage1->root_name_len = strlen(out_name);
|
||||
stage1->strip = strip;
|
||||
|
@ -295,3 +459,66 @@ int main(int argc, char **argv) {
|
|||
|
||||
return main_exit(root_progress_node, EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
void stage2_panic(const char *ptr, size_t len) {
|
||||
fwrite(ptr, 1, len, stderr);
|
||||
fprintf(stderr, "\n");
|
||||
fflush(stderr);
|
||||
abort();
|
||||
}
|
||||
|
||||
struct Stage2Progress {
|
||||
int trash;
|
||||
};
|
||||
|
||||
struct Stage2ProgressNode {
|
||||
int trash;
|
||||
};
|
||||
|
||||
Stage2Progress *stage2_progress_create(void) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void stage2_progress_destroy(Stage2Progress *progress) {}
|
||||
|
||||
Stage2ProgressNode *stage2_progress_start_root(Stage2Progress *progress,
|
||||
const char *name_ptr, size_t name_len, size_t estimated_total_items)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
Stage2ProgressNode *stage2_progress_start(Stage2ProgressNode *node,
|
||||
const char *name_ptr, size_t name_len, size_t estimated_total_items)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
void stage2_progress_end(Stage2ProgressNode *node) {}
|
||||
void stage2_progress_complete_one(Stage2ProgressNode *node) {}
|
||||
void stage2_progress_disable_tty(Stage2Progress *progress) {}
|
||||
void stage2_progress_update_node(Stage2ProgressNode *node, size_t completed_count, size_t estimated_total_items){}
|
||||
|
||||
const char *stage2_fetch_file(struct ZigStage1 *stage1, const char *path_ptr, size_t path_len,
|
||||
size_t *result_len)
|
||||
{
|
||||
Error err;
|
||||
Buf contents_buf = BUF_INIT;
|
||||
Buf path_buf = BUF_INIT;
|
||||
|
||||
buf_init_from_mem(&path_buf, path_ptr, path_len);
|
||||
if ((err = os_fetch_file_path(&path_buf, &contents_buf))) {
|
||||
return nullptr;
|
||||
}
|
||||
*result_len = buf_len(&contents_buf);
|
||||
return buf_ptr(&contents_buf);
|
||||
}
|
||||
|
||||
const char *stage2_cimport(struct ZigStage1 *stage1) {
|
||||
const char *msg = "stage0 called stage2_cimport";
|
||||
stage2_panic(msg, strlen(msg));
|
||||
}
|
||||
|
||||
const char *stage2_add_link_lib(struct ZigStage1 *stage1,
|
||||
const char *lib_name_ptr, size_t lib_name_len,
|
||||
const char *symbol_name_ptr, size_t symbol_name_len)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue