stage2: compiling C objects with clang
* add target_util.zig which has ported code from src/target.cpp * Module gains an arena that owns memory used during initialization that has the same lifetime as the Module. Useful for constructing file paths and lists of strings that have mixed lifetimes. - The Module memory itself is allocated in this arena. init/deinit are modified to be create/destroy. - root_name moves to the arena and no longer needs manual free * implement the ability to invoke `zig clang` as a subprocess - there are lots of TODOs that should be solved before merging * Module now requires a Random object and zig_lib_dir * Module now requires a path to its own executable or any zig executable that can do `zig clang`. * Wire up more CLI options. * Module creates "zig-cache" directory and "tmp" and "o" subdirectories ("h" is created by the cache_hash) * stubbed out some of the things linker code needs to do with TODO prints * delete dead code for computing compiler id. the previous commit eliminated the need for it. * add `zig translate-c` CLI option but it's not fully hooked up yet. It should be possible for this to be fully wired up before merging this branch. * `zig targets` now uses canonical data for available_libcs
This commit is contained in:
parent
c99e34a00e
commit
193ad413f0
File diff suppressed because it is too large
Load Diff
125
src-self-hosted/codegen/llvm.zig
Normal file
125
src-self-hosted/codegen/llvm.zig
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
const Allocator = std.mem.Allocator;
|
||||||
|
|
||||||
|
pub fn targetTriple(allocator: *Allocator, target: std.Target) ![]u8 {
|
||||||
|
const llvm_arch = switch (target.cpu.arch) {
|
||||||
|
.arm => "arm",
|
||||||
|
.armeb => "armeb",
|
||||||
|
.aarch64 => "aarch64",
|
||||||
|
.aarch64_be => "aarch64_be",
|
||||||
|
.aarch64_32 => "aarch64_32",
|
||||||
|
.arc => "arc",
|
||||||
|
.avr => "avr",
|
||||||
|
.bpfel => "bpfel",
|
||||||
|
.bpfeb => "bpfeb",
|
||||||
|
.hexagon => "hexagon",
|
||||||
|
.mips => "mips",
|
||||||
|
.mipsel => "mipsel",
|
||||||
|
.mips64 => "mips64",
|
||||||
|
.mips64el => "mips64el",
|
||||||
|
.msp430 => "msp430",
|
||||||
|
.powerpc => "powerpc",
|
||||||
|
.powerpc64 => "powerpc64",
|
||||||
|
.powerpc64le => "powerpc64le",
|
||||||
|
.r600 => "r600",
|
||||||
|
.amdgcn => "amdgcn",
|
||||||
|
.riscv32 => "riscv32",
|
||||||
|
.riscv64 => "riscv64",
|
||||||
|
.sparc => "sparc",
|
||||||
|
.sparcv9 => "sparcv9",
|
||||||
|
.sparcel => "sparcel",
|
||||||
|
.s390x => "s390x",
|
||||||
|
.tce => "tce",
|
||||||
|
.tcele => "tcele",
|
||||||
|
.thumb => "thumb",
|
||||||
|
.thumbeb => "thumbeb",
|
||||||
|
.i386 => "i386",
|
||||||
|
.x86_64 => "x86_64",
|
||||||
|
.xcore => "xcore",
|
||||||
|
.nvptx => "nvptx",
|
||||||
|
.nvptx64 => "nvptx64",
|
||||||
|
.le32 => "le32",
|
||||||
|
.le64 => "le64",
|
||||||
|
.amdil => "amdil",
|
||||||
|
.amdil64 => "amdil64",
|
||||||
|
.hsail => "hsail",
|
||||||
|
.hsail64 => "hsail64",
|
||||||
|
.spir => "spir",
|
||||||
|
.spir64 => "spir64",
|
||||||
|
.kalimba => "kalimba",
|
||||||
|
.shave => "shave",
|
||||||
|
.lanai => "lanai",
|
||||||
|
.wasm32 => "wasm32",
|
||||||
|
.wasm64 => "wasm64",
|
||||||
|
.renderscript32 => "renderscript32",
|
||||||
|
.renderscript64 => "renderscript64",
|
||||||
|
.ve => "ve",
|
||||||
|
.spu_2 => return error.LLVMBackendDoesNotSupportSPUMarkII,
|
||||||
|
};
|
||||||
|
// TODO Add a sub-arch for some architectures depending on CPU features.
|
||||||
|
|
||||||
|
const llvm_os = switch (target.os.tag) {
|
||||||
|
.freestanding => "unknown",
|
||||||
|
.ananas => "ananas",
|
||||||
|
.cloudabi => "cloudabi",
|
||||||
|
.dragonfly => "dragonfly",
|
||||||
|
.freebsd => "freebsd",
|
||||||
|
.fuchsia => "fuchsia",
|
||||||
|
.ios => "ios",
|
||||||
|
.kfreebsd => "kfreebsd",
|
||||||
|
.linux => "linux",
|
||||||
|
.lv2 => "lv2",
|
||||||
|
.macosx => "macosx",
|
||||||
|
.netbsd => "netbsd",
|
||||||
|
.openbsd => "openbsd",
|
||||||
|
.solaris => "solaris",
|
||||||
|
.windows => "windows",
|
||||||
|
.haiku => "haiku",
|
||||||
|
.minix => "minix",
|
||||||
|
.rtems => "rtems",
|
||||||
|
.nacl => "nacl",
|
||||||
|
.cnk => "cnk",
|
||||||
|
.aix => "aix",
|
||||||
|
.cuda => "cuda",
|
||||||
|
.nvcl => "nvcl",
|
||||||
|
.amdhsa => "amdhsa",
|
||||||
|
.ps4 => "ps4",
|
||||||
|
.elfiamcu => "elfiamcu",
|
||||||
|
.tvos => "tvos",
|
||||||
|
.watchos => "watchos",
|
||||||
|
.mesa3d => "mesa3d",
|
||||||
|
.contiki => "contiki",
|
||||||
|
.amdpal => "amdpal",
|
||||||
|
.hermit => "hermit",
|
||||||
|
.hurd => "hurd",
|
||||||
|
.wasi => "wasi",
|
||||||
|
.emscripten => "emscripten",
|
||||||
|
.uefi => "windows",
|
||||||
|
.other => "unknown",
|
||||||
|
};
|
||||||
|
|
||||||
|
const llvm_abi = switch (target.abi) {
|
||||||
|
.none => "unknown",
|
||||||
|
.gnu => "gnu",
|
||||||
|
.gnuabin32 => "gnuabin32",
|
||||||
|
.gnuabi64 => "gnuabi64",
|
||||||
|
.gnueabi => "gnueabi",
|
||||||
|
.gnueabihf => "gnueabihf",
|
||||||
|
.gnux32 => "gnux32",
|
||||||
|
.code16 => "code16",
|
||||||
|
.eabi => "eabi",
|
||||||
|
.eabihf => "eabihf",
|
||||||
|
.android => "android",
|
||||||
|
.musl => "musl",
|
||||||
|
.musleabi => "musleabi",
|
||||||
|
.musleabihf => "musleabihf",
|
||||||
|
.msvc => "msvc",
|
||||||
|
.itanium => "itanium",
|
||||||
|
.cygnus => "cygnus",
|
||||||
|
.coreclr => "coreclr",
|
||||||
|
.simulator => "simulator",
|
||||||
|
.macabi => "macabi",
|
||||||
|
};
|
||||||
|
|
||||||
|
return std.fmt.allocPrint(allocator, "{}-unknown-{}-{}", .{ llvm_arch, llvm_os, llvm_abi });
|
||||||
|
}
|
@ -93,46 +93,3 @@ pub fn openGlobalCacheDir() !fs.Dir {
|
|||||||
const path_name = try resolveGlobalCacheDir(&fba.allocator);
|
const path_name = try resolveGlobalCacheDir(&fba.allocator);
|
||||||
return fs.cwd().makeOpenPath(path_name, .{});
|
return fs.cwd().makeOpenPath(path_name, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
var compiler_id_mutex = std.Mutex{};
|
|
||||||
var compiler_id: [16]u8 = undefined;
|
|
||||||
var compiler_id_computed = false;
|
|
||||||
|
|
||||||
pub fn resolveCompilerId(gpa: *mem.Allocator) ![16]u8 {
|
|
||||||
const held = compiler_id_mutex.acquire();
|
|
||||||
defer held.release();
|
|
||||||
|
|
||||||
if (compiler_id_computed)
|
|
||||||
return compiler_id;
|
|
||||||
compiler_id_computed = true;
|
|
||||||
|
|
||||||
var cache_dir = try openGlobalCacheDir();
|
|
||||||
defer cache_dir.close();
|
|
||||||
|
|
||||||
var ch = try CacheHash.init(gpa, cache_dir, "exe");
|
|
||||||
defer ch.release();
|
|
||||||
|
|
||||||
const self_exe_path = try fs.selfExePathAlloc(gpa);
|
|
||||||
defer gpa.free(self_exe_path);
|
|
||||||
|
|
||||||
_ = try ch.addFile(self_exe_path, null);
|
|
||||||
|
|
||||||
if (try ch.hit()) |digest| {
|
|
||||||
compiler_id = digest[0..16].*;
|
|
||||||
return compiler_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
const libs = try std.process.getSelfExeSharedLibPaths(gpa);
|
|
||||||
defer {
|
|
||||||
for (libs) |lib| gpa.free(lib);
|
|
||||||
gpa.free(libs);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (libs) |lib| {
|
|
||||||
try ch.addFilePost(lib);
|
|
||||||
}
|
|
||||||
|
|
||||||
const digest = ch.final();
|
|
||||||
compiler_id = digest[0..16].*;
|
|
||||||
return compiler_id;
|
|
||||||
}
|
|
||||||
|
@ -35,6 +35,9 @@ pub const Options = struct {
|
|||||||
/// other objects.
|
/// other objects.
|
||||||
/// Otherwise (depending on `use_lld`) this link code directly outputs and updates the final binary.
|
/// Otherwise (depending on `use_lld`) this link code directly outputs and updates the final binary.
|
||||||
use_llvm: bool = false,
|
use_llvm: bool = false,
|
||||||
|
link_libc: bool = false,
|
||||||
|
link_libcpp: bool = false,
|
||||||
|
function_sections: bool = false,
|
||||||
|
|
||||||
objects: []const []const u8 = &[0][]const u8{},
|
objects: []const []const u8 = &[0][]const u8{},
|
||||||
framework_dirs: []const []const u8 = &[0][]const u8{},
|
framework_dirs: []const []const u8 = &[0][]const u8{},
|
||||||
|
@ -219,8 +219,11 @@ pub const SrcFn = struct {
|
|||||||
pub fn openPath(allocator: *Allocator, dir: fs.Dir, sub_path: []const u8, options: link.Options) !*File {
|
pub fn openPath(allocator: *Allocator, dir: fs.Dir, sub_path: []const u8, options: link.Options) !*File {
|
||||||
assert(options.object_format == .elf);
|
assert(options.object_format == .elf);
|
||||||
|
|
||||||
if (options.use_llvm) return error.LLVM_BackendIsTODO_ForELF; // TODO
|
if (options.use_llvm) return error.LLVMBackendUnimplementedForELF; // TODO
|
||||||
if (options.use_lld) return error.LLD_LinkingIsTODOForELF; // TODO
|
|
||||||
|
if (build_options.have_llvm and options.use_lld) {
|
||||||
|
std.debug.print("TODO open a temporary object file, not the final output file because we want to link with LLD\n", .{});
|
||||||
|
}
|
||||||
|
|
||||||
const file = try dir.createFile(sub_path, .{ .truncate = false, .read = true, .mode = link.determineMode(options) });
|
const file = try dir.createFile(sub_path, .{ .truncate = false, .read = true, .mode = link.determineMode(options) });
|
||||||
errdefer file.close();
|
errdefer file.close();
|
||||||
@ -741,8 +744,21 @@ pub const abbrev_base_type = 4;
|
|||||||
pub const abbrev_pad1 = 5;
|
pub const abbrev_pad1 = 5;
|
||||||
pub const abbrev_parameter = 6;
|
pub const abbrev_parameter = 6;
|
||||||
|
|
||||||
/// Commit pending changes and write headers.
|
|
||||||
pub fn flush(self: *Elf, module: *Module) !void {
|
pub fn flush(self: *Elf, module: *Module) !void {
|
||||||
|
if (build_options.have_llvm and self.base.options.use_lld) {
|
||||||
|
// 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.
|
||||||
|
if (module.root_pkg != null) {
|
||||||
|
try self.flushInner(module);
|
||||||
|
}
|
||||||
|
std.debug.print("TODO create an LLD command line and invoke it\n", .{});
|
||||||
|
} else {
|
||||||
|
return self.flushInner(module);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Commit pending changes and write headers.
|
||||||
|
fn flushInner(self: *Elf, module: *Module) !void {
|
||||||
const target_endian = self.base.options.target.cpu.arch.endian();
|
const target_endian = self.base.options.target.cpu.arch.endian();
|
||||||
const foreign_endian = target_endian != std.Target.current.cpu.arch.endian();
|
const foreign_endian = target_endian != std.Target.current.cpu.arch.endian();
|
||||||
const ptr_width_bytes: u8 = self.ptrWidthBytes();
|
const ptr_width_bytes: u8 = self.ptrWidthBytes();
|
||||||
|
@ -33,13 +33,14 @@ const usage =
|
|||||||
\\
|
\\
|
||||||
\\Commands:
|
\\Commands:
|
||||||
\\
|
\\
|
||||||
\\ build-exe [source] Create executable from source or object files
|
\\ build-exe [source] Create executable from source or object files
|
||||||
\\ build-lib [source] Create library from source or object files
|
\\ build-lib [source] Create library from source or object files
|
||||||
\\ build-obj [source] Create object from source or assembly
|
\\ build-obj [source] Create object from source or assembly
|
||||||
\\ cc Use Zig as a drop-in C compiler
|
\\ cc Use Zig as a drop-in C compiler
|
||||||
\\ c++ Use Zig as a drop-in C++ compiler
|
\\ c++ Use Zig as a drop-in C++ compiler
|
||||||
\\ env Print lib path, std path, compiler id and version
|
\\ env Print lib path, std path, compiler id and version
|
||||||
\\ fmt [source] Parse file and render in canonical zig format
|
\\ fmt [source] Parse file and render in canonical zig format
|
||||||
|
\\ translate-c [source] Convert C code to Zig code
|
||||||
\\ targets List available compilation targets
|
\\ targets List available compilation targets
|
||||||
\\ version Print version number and exit
|
\\ version Print version number and exit
|
||||||
\\ zen Print zen of zig and exit
|
\\ zen Print zen of zig and exit
|
||||||
@ -47,15 +48,21 @@ const usage =
|
|||||||
\\
|
\\
|
||||||
;
|
;
|
||||||
|
|
||||||
|
pub const log_level: std.log.Level = switch (std.builtin.mode) {
|
||||||
|
.Debug => .debug,
|
||||||
|
.ReleaseSafe, .ReleaseFast => .info,
|
||||||
|
.ReleaseSmall => .crit,
|
||||||
|
};
|
||||||
|
|
||||||
pub fn log(
|
pub fn log(
|
||||||
comptime level: std.log.Level,
|
comptime level: std.log.Level,
|
||||||
comptime scope: @TypeOf(.EnumLiteral),
|
comptime scope: @TypeOf(.EnumLiteral),
|
||||||
comptime format: []const u8,
|
comptime format: []const u8,
|
||||||
args: anytype,
|
args: anytype,
|
||||||
) void {
|
) void {
|
||||||
// Hide anything more verbose than warn unless it was added with `-Dlog=foo`.
|
// Hide debug messages unless added with `-Dlog=foo`.
|
||||||
if (@enumToInt(level) > @enumToInt(std.log.level) or
|
if (@enumToInt(level) > @enumToInt(std.log.level) or
|
||||||
@enumToInt(level) > @enumToInt(std.log.Level.warn))
|
@enumToInt(level) > @enumToInt(std.log.Level.info))
|
||||||
{
|
{
|
||||||
const scope_name = @tagName(scope);
|
const scope_name = @tagName(scope);
|
||||||
const ok = comptime for (build_options.log_scopes) |log_scope| {
|
const ok = comptime for (build_options.log_scopes) |log_scope| {
|
||||||
@ -67,13 +74,15 @@ pub fn log(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We only recognize 4 log levels in this application.
|
||||||
const level_txt = switch (level) {
|
const level_txt = switch (level) {
|
||||||
.emerg => "error",
|
.emerg, .alert, .crit => "error",
|
||||||
.warn => "warning",
|
.err, .warn => "warning",
|
||||||
else => @tagName(level),
|
.notice, .info => "info",
|
||||||
|
.debug => "debug",
|
||||||
};
|
};
|
||||||
const prefix1 = level_txt ++ ": ";
|
const prefix1 = level_txt;
|
||||||
const prefix2 = if (scope == .default) "" else "(" ++ @tagName(scope) ++ "): ";
|
const prefix2 = if (scope == .default) ": " else "(" ++ @tagName(scope) ++ "): ";
|
||||||
|
|
||||||
// Print the message to stderr, silently ignoring any errors
|
// Print the message to stderr, silently ignoring any errors
|
||||||
std.debug.print(prefix1 ++ prefix2 ++ format ++ "\n", args);
|
std.debug.print(prefix1 ++ prefix2 ++ format ++ "\n", args);
|
||||||
@ -93,8 +102,8 @@ pub fn main() !void {
|
|||||||
const args = try process.argsAlloc(arena);
|
const args = try process.argsAlloc(arena);
|
||||||
|
|
||||||
if (args.len <= 1) {
|
if (args.len <= 1) {
|
||||||
std.debug.print("expected command argument\n\n{}", .{usage});
|
std.log.info("{}", .{usage});
|
||||||
process.exit(1);
|
fatal("expected command argument", .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
const cmd = args[1];
|
const cmd = args[1];
|
||||||
@ -109,6 +118,8 @@ pub fn main() !void {
|
|||||||
return buildOutputType(gpa, arena, args, .cc);
|
return buildOutputType(gpa, arena, args, .cc);
|
||||||
} else if (mem.eql(u8, cmd, "c++")) {
|
} else if (mem.eql(u8, cmd, "c++")) {
|
||||||
return buildOutputType(gpa, arena, args, .cpp);
|
return buildOutputType(gpa, arena, args, .cpp);
|
||||||
|
} else if (mem.eql(u8, cmd, "translate-c")) {
|
||||||
|
return buildOutputType(gpa, arena, args, .translate_c);
|
||||||
} else if (mem.eql(u8, cmd, "clang") or
|
} else if (mem.eql(u8, cmd, "clang") or
|
||||||
mem.eql(u8, cmd, "-cc1") or mem.eql(u8, cmd, "-cc1as"))
|
mem.eql(u8, cmd, "-cc1") or mem.eql(u8, cmd, "-cc1as"))
|
||||||
{
|
{
|
||||||
@ -128,8 +139,8 @@ pub fn main() !void {
|
|||||||
} else if (mem.eql(u8, cmd, "help")) {
|
} else if (mem.eql(u8, cmd, "help")) {
|
||||||
try io.getStdOut().writeAll(usage);
|
try io.getStdOut().writeAll(usage);
|
||||||
} else {
|
} else {
|
||||||
std.debug.print("unknown command: {}\n\n{}", .{ args[1], usage });
|
std.log.info("{}", .{usage});
|
||||||
process.exit(1);
|
fatal("unknown command: {}", .{args[1]});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -223,6 +234,7 @@ pub fn buildOutputType(
|
|||||||
build: std.builtin.OutputMode,
|
build: std.builtin.OutputMode,
|
||||||
cc,
|
cc,
|
||||||
cpp,
|
cpp,
|
||||||
|
translate_c,
|
||||||
},
|
},
|
||||||
) !void {
|
) !void {
|
||||||
var color: Color = .Auto;
|
var color: Color = .Auto;
|
||||||
@ -251,8 +263,8 @@ pub fn buildOutputType(
|
|||||||
var emit_h: Emit = undefined;
|
var emit_h: Emit = undefined;
|
||||||
var ensure_libc_on_non_freestanding = false;
|
var ensure_libc_on_non_freestanding = false;
|
||||||
var ensure_libcpp_on_non_freestanding = false;
|
var ensure_libcpp_on_non_freestanding = false;
|
||||||
var have_libc = false;
|
var link_libc = false;
|
||||||
var have_libcpp = false;
|
var link_libcpp = false;
|
||||||
var want_native_include_dirs = false;
|
var want_native_include_dirs = false;
|
||||||
var enable_cache: ?bool = null;
|
var enable_cache: ?bool = null;
|
||||||
var want_pic: ?bool = null;
|
var want_pic: ?bool = null;
|
||||||
@ -298,13 +310,20 @@ pub fn buildOutputType(
|
|||||||
var frameworks = std.ArrayList([]const u8).init(gpa);
|
var frameworks = std.ArrayList([]const u8).init(gpa);
|
||||||
defer frameworks.deinit();
|
defer frameworks.deinit();
|
||||||
|
|
||||||
if (arg_mode == .build) {
|
if (arg_mode == .build or arg_mode == .translate_c) {
|
||||||
output_mode = arg_mode.build;
|
output_mode = switch (arg_mode) {
|
||||||
emit_h = switch (output_mode) {
|
.build => |m| m,
|
||||||
.Exe => .no,
|
.translate_c => .Obj,
|
||||||
.Obj, .Lib => .yes_default_path,
|
else => unreachable,
|
||||||
};
|
};
|
||||||
|
switch (arg_mode) {
|
||||||
|
.build => switch (output_mode) {
|
||||||
|
.Exe => emit_h = .no,
|
||||||
|
.Obj, .Lib => emit_h = .yes_default_path,
|
||||||
|
},
|
||||||
|
.translate_c => emit_h = .no,
|
||||||
|
else => unreachable,
|
||||||
|
}
|
||||||
const args = all_args[2..];
|
const args = all_args[2..];
|
||||||
var i: usize = 0;
|
var i: usize = 0;
|
||||||
while (i < args.len) : (i += 1) {
|
while (i < args.len) : (i += 1) {
|
||||||
@ -499,7 +518,7 @@ pub fn buildOutputType(
|
|||||||
mem.endsWith(u8, arg, ".lib"))
|
mem.endsWith(u8, arg, ".lib"))
|
||||||
{
|
{
|
||||||
try link_objects.append(arg);
|
try link_objects.append(arg);
|
||||||
} else if (hasAsmExt(arg) or hasCExt(arg) or hasCppExt(arg)) {
|
} else if (Module.hasAsmExt(arg) or Module.hasCExt(arg) or Module.hasCppExt(arg)) {
|
||||||
try c_source_files.append(arg);
|
try c_source_files.append(arg);
|
||||||
} else if (mem.endsWith(u8, arg, ".so") or
|
} else if (mem.endsWith(u8, arg, ".so") or
|
||||||
mem.endsWith(u8, arg, ".dylib") or
|
mem.endsWith(u8, arg, ".dylib") or
|
||||||
@ -543,7 +562,7 @@ pub fn buildOutputType(
|
|||||||
try clang_argv.appendSlice(it.other_args);
|
try clang_argv.appendSlice(it.other_args);
|
||||||
},
|
},
|
||||||
.positional => {
|
.positional => {
|
||||||
const file_ext = classify_file_ext(mem.spanZ(it.only_arg));
|
const file_ext = Module.classifyFileExt(mem.spanZ(it.only_arg));
|
||||||
switch (file_ext) {
|
switch (file_ext) {
|
||||||
.assembly, .c, .cpp, .ll, .bc, .h => try c_source_files.append(it.only_arg),
|
.assembly, .c, .cpp, .ll, .bc, .h => try c_source_files.append(it.only_arg),
|
||||||
.unknown => try link_objects.append(it.only_arg),
|
.unknown => try link_objects.append(it.only_arg),
|
||||||
@ -819,28 +838,28 @@ pub fn buildOutputType(
|
|||||||
.diagnostics = &diags,
|
.diagnostics = &diags,
|
||||||
}) catch |err| switch (err) {
|
}) catch |err| switch (err) {
|
||||||
error.UnknownCpuModel => {
|
error.UnknownCpuModel => {
|
||||||
std.debug.print("Unknown CPU: '{}'\nAvailable CPUs for architecture '{}':\n", .{
|
help: {
|
||||||
diags.cpu_name.?,
|
var help_text = std.ArrayList(u8).init(arena);
|
||||||
@tagName(diags.arch.?),
|
for (diags.arch.?.allCpuModels()) |cpu| {
|
||||||
});
|
help_text.writer().print(" {}\n", .{cpu.name}) catch break :help;
|
||||||
for (diags.arch.?.allCpuModels()) |cpu| {
|
}
|
||||||
std.debug.print(" {}\n", .{cpu.name});
|
std.log.info("Available CPUs for architecture '{}': {}", .{
|
||||||
|
@tagName(diags.arch.?), help_text.items,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
process.exit(1);
|
fatal("Unknown CPU: '{}'", .{diags.cpu_name.?});
|
||||||
},
|
},
|
||||||
error.UnknownCpuFeature => {
|
error.UnknownCpuFeature => {
|
||||||
std.debug.print(
|
help: {
|
||||||
\\Unknown CPU feature: '{}'
|
var help_text = std.ArrayList(u8).init(arena);
|
||||||
\\Available CPU features for architecture '{}':
|
for (diags.arch.?.allFeaturesList()) |feature| {
|
||||||
\\
|
help_text.writer().print(" {}: {}\n", .{ feature.name, feature.description }) catch break :help;
|
||||||
, .{
|
}
|
||||||
diags.unknown_feature_name,
|
std.log.info("Available CPU features for architecture '{}': {}", .{
|
||||||
@tagName(diags.arch.?),
|
@tagName(diags.arch.?), help_text.items,
|
||||||
});
|
});
|
||||||
for (diags.arch.?.allFeaturesList()) |feature| {
|
|
||||||
std.debug.print(" {}: {}\n", .{ feature.name, feature.description });
|
|
||||||
}
|
}
|
||||||
process.exit(1);
|
fatal("Unknown CPU feature: '{}'", .{diags.unknown_feature_name});
|
||||||
},
|
},
|
||||||
else => |e| return e,
|
else => |e| return e,
|
||||||
};
|
};
|
||||||
@ -849,14 +868,16 @@ pub fn buildOutputType(
|
|||||||
if (target_info.cpu_detection_unimplemented) {
|
if (target_info.cpu_detection_unimplemented) {
|
||||||
// TODO We want to just use detected_info.target but implementing
|
// TODO We want to just use detected_info.target but implementing
|
||||||
// CPU model & feature detection is todo so here we rely on LLVM.
|
// CPU model & feature detection is todo so here we rely on LLVM.
|
||||||
|
// TODO The workaround to use LLVM to detect features needs to be used for
|
||||||
|
// `zig targets` as well.
|
||||||
fatal("CPU features detection is not yet available for this system without LLVM extensions", .{});
|
fatal("CPU features detection is not yet available for this system without LLVM extensions", .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (target_info.target.os.tag != .freestanding) {
|
if (target_info.target.os.tag != .freestanding) {
|
||||||
if (ensure_libc_on_non_freestanding)
|
if (ensure_libc_on_non_freestanding)
|
||||||
have_libc = true;
|
link_libc = true;
|
||||||
if (ensure_libcpp_on_non_freestanding)
|
if (ensure_libcpp_on_non_freestanding)
|
||||||
have_libcpp = true;
|
link_libcpp = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now that we have target info, we can find out if any of the system libraries
|
// Now that we have target info, we can find out if any of the system libraries
|
||||||
@ -867,12 +888,12 @@ pub fn buildOutputType(
|
|||||||
while (i < system_libs.items.len) {
|
while (i < system_libs.items.len) {
|
||||||
const lib_name = system_libs.items[i];
|
const lib_name = system_libs.items[i];
|
||||||
if (is_libc_lib_name(target_info.target, lib_name)) {
|
if (is_libc_lib_name(target_info.target, lib_name)) {
|
||||||
have_libc = true;
|
link_libc = true;
|
||||||
_ = system_libs.orderedRemove(i);
|
_ = system_libs.orderedRemove(i);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (is_libcpp_lib_name(target_info.target, lib_name)) {
|
if (is_libcpp_lib_name(target_info.target, lib_name)) {
|
||||||
have_libcpp = true;
|
link_libcpp = true;
|
||||||
_ = system_libs.orderedRemove(i);
|
_ = system_libs.orderedRemove(i);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -960,7 +981,21 @@ pub fn buildOutputType(
|
|||||||
.yes_default_path => try std.fmt.allocPrint(arena, "{}.h", .{root_name}),
|
.yes_default_path => try std.fmt.allocPrint(arena, "{}.h", .{root_name}),
|
||||||
};
|
};
|
||||||
|
|
||||||
var module = Module.init(gpa, .{
|
const self_exe_path = try fs.selfExePathAlloc(arena);
|
||||||
|
const zig_lib_dir = introspect.resolveZigLibDir(gpa) catch |err| {
|
||||||
|
fatal("unable to find zig installation directory: {}\n", .{@errorName(err)});
|
||||||
|
};
|
||||||
|
defer gpa.free(zig_lib_dir);
|
||||||
|
|
||||||
|
const random_seed = blk: {
|
||||||
|
var random_seed: u64 = undefined;
|
||||||
|
try std.crypto.randomBytes(mem.asBytes(&random_seed));
|
||||||
|
break :blk random_seed;
|
||||||
|
};
|
||||||
|
var default_prng = std.rand.DefaultPrng.init(random_seed);
|
||||||
|
|
||||||
|
const module = Module.create(gpa, .{
|
||||||
|
.zig_lib_dir = zig_lib_dir,
|
||||||
.root_name = root_name,
|
.root_name = root_name,
|
||||||
.target = target_info.target,
|
.target = target_info.target,
|
||||||
.output_mode = output_mode,
|
.output_mode = output_mode,
|
||||||
@ -980,8 +1015,8 @@ pub fn buildOutputType(
|
|||||||
.frameworks = frameworks.items,
|
.frameworks = frameworks.items,
|
||||||
.system_libs = system_libs.items,
|
.system_libs = system_libs.items,
|
||||||
.emit_h = emit_h_path,
|
.emit_h = emit_h_path,
|
||||||
.have_libc = have_libc,
|
.link_libc = link_libc,
|
||||||
.have_libcpp = have_libcpp,
|
.link_libcpp = link_libcpp,
|
||||||
.want_pic = want_pic,
|
.want_pic = want_pic,
|
||||||
.want_sanitize_c = want_sanitize_c,
|
.want_sanitize_c = want_sanitize_c,
|
||||||
.use_llvm = use_llvm,
|
.use_llvm = use_llvm,
|
||||||
@ -1000,16 +1035,19 @@ pub fn buildOutputType(
|
|||||||
.linker_z_defs = linker_z_defs,
|
.linker_z_defs = linker_z_defs,
|
||||||
.stack_size_override = stack_size_override,
|
.stack_size_override = stack_size_override,
|
||||||
.strip = strip,
|
.strip = strip,
|
||||||
|
.self_exe_path = self_exe_path,
|
||||||
|
.rand = &default_prng.random,
|
||||||
|
.clang_passthrough_mode = arg_mode != .build,
|
||||||
}) catch |err| {
|
}) catch |err| {
|
||||||
fatal("unable to initialize module: {}", .{@errorName(err)});
|
fatal("unable to create module: {}", .{@errorName(err)});
|
||||||
};
|
};
|
||||||
defer module.deinit();
|
defer module.destroy();
|
||||||
|
|
||||||
const stdin = std.io.getStdIn().inStream();
|
const stdin = std.io.getStdIn().inStream();
|
||||||
const stderr = std.io.getStdErr().outStream();
|
const stderr = std.io.getStdErr().outStream();
|
||||||
var repl_buf: [1024]u8 = undefined;
|
var repl_buf: [1024]u8 = undefined;
|
||||||
|
|
||||||
try updateModule(gpa, &module, zir_out_path);
|
try updateModule(gpa, module, zir_out_path);
|
||||||
|
|
||||||
if (build_options.have_llvm and only_pp_or_asm) {
|
if (build_options.have_llvm and only_pp_or_asm) {
|
||||||
// this may include dumping the output to stdout
|
// this may include dumping the output to stdout
|
||||||
@ -1031,7 +1069,7 @@ pub fn buildOutputType(
|
|||||||
if (output_mode == .Exe) {
|
if (output_mode == .Exe) {
|
||||||
try module.makeBinFileWritable();
|
try module.makeBinFileWritable();
|
||||||
}
|
}
|
||||||
try updateModule(gpa, &module, zir_out_path);
|
try updateModule(gpa, module, zir_out_path);
|
||||||
} else if (mem.eql(u8, actual_line, "exit")) {
|
} else if (mem.eql(u8, actual_line, "exit")) {
|
||||||
break;
|
break;
|
||||||
} else if (mem.eql(u8, actual_line, "help")) {
|
} else if (mem.eql(u8, actual_line, "help")) {
|
||||||
@ -1062,12 +1100,10 @@ fn updateModule(gpa: *Allocator, module: *Module, zir_out_path: ?[]const u8) !vo
|
|||||||
full_err_msg.msg,
|
full_err_msg.msg,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
std.log.info("Update completed in {} ms", .{update_nanos / std.time.ns_per_ms});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (zir_out_path) |zop| {
|
if (zir_out_path) |zop| {
|
||||||
var new_zir_module = try zir.emit(gpa, module.*);
|
var new_zir_module = try zir.emit(gpa, module);
|
||||||
defer new_zir_module.deinit(gpa);
|
defer new_zir_module.deinit(gpa);
|
||||||
|
|
||||||
const baf = try io.BufferedAtomicFile.create(gpa, fs.cwd(), zop, .{});
|
const baf = try io.BufferedAtomicFile.create(gpa, fs.cwd(), zop, .{});
|
||||||
@ -1422,50 +1458,6 @@ pub const info_zen =
|
|||||||
\\
|
\\
|
||||||
;
|
;
|
||||||
|
|
||||||
const FileExt = enum {
|
|
||||||
c,
|
|
||||||
cpp,
|
|
||||||
h,
|
|
||||||
ll,
|
|
||||||
bc,
|
|
||||||
assembly,
|
|
||||||
unknown,
|
|
||||||
};
|
|
||||||
|
|
||||||
fn hasCExt(filename: []const u8) bool {
|
|
||||||
return mem.endsWith(u8, filename, ".c");
|
|
||||||
}
|
|
||||||
|
|
||||||
fn hasCppExt(filename: []const u8) bool {
|
|
||||||
return mem.endsWith(u8, filename, ".C") or
|
|
||||||
mem.endsWith(u8, filename, ".cc") or
|
|
||||||
mem.endsWith(u8, filename, ".cpp") or
|
|
||||||
mem.endsWith(u8, filename, ".cxx");
|
|
||||||
}
|
|
||||||
|
|
||||||
fn hasAsmExt(filename: []const u8) bool {
|
|
||||||
return mem.endsWith(u8, filename, ".s") or mem.endsWith(u8, filename, ".S");
|
|
||||||
}
|
|
||||||
|
|
||||||
fn classify_file_ext(filename: []const u8) FileExt {
|
|
||||||
if (hasCExt(filename)) {
|
|
||||||
return .c;
|
|
||||||
} else if (hasCppExt(filename)) {
|
|
||||||
return .cpp;
|
|
||||||
} else if (mem.endsWith(u8, filename, ".ll")) {
|
|
||||||
return .ll;
|
|
||||||
} else if (mem.endsWith(u8, filename, ".bc")) {
|
|
||||||
return .bc;
|
|
||||||
} else if (hasAsmExt(filename)) {
|
|
||||||
return .assembly;
|
|
||||||
} else if (mem.endsWith(u8, filename, ".h")) {
|
|
||||||
return .h;
|
|
||||||
} else {
|
|
||||||
// TODO look for .so, .so.X, .so.X.Y, .so.X.Y.Z
|
|
||||||
return .unknown;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "c" fn ZigClang_main(argc: c_int, argv: [*:null]?[*:0]u8) c_int;
|
extern "c" fn ZigClang_main(argc: c_int, argv: [*:null]?[*:0]u8) c_int;
|
||||||
|
|
||||||
/// TODO make it so the return value can be !noreturn
|
/// TODO make it so the return value can be !noreturn
|
||||||
|
@ -4,60 +4,11 @@ const io = std.io;
|
|||||||
const mem = std.mem;
|
const mem = std.mem;
|
||||||
const Allocator = mem.Allocator;
|
const Allocator = mem.Allocator;
|
||||||
const Target = std.Target;
|
const Target = std.Target;
|
||||||
|
const target = @import("target.zig");
|
||||||
const assert = std.debug.assert;
|
const assert = std.debug.assert;
|
||||||
|
|
||||||
const introspect = @import("introspect.zig");
|
const introspect = @import("introspect.zig");
|
||||||
|
|
||||||
// TODO this is hard-coded until self-hosted gains this information canonically
|
|
||||||
const available_libcs = [_][]const u8{
|
|
||||||
"aarch64_be-linux-gnu",
|
|
||||||
"aarch64_be-linux-musl",
|
|
||||||
"aarch64_be-windows-gnu",
|
|
||||||
"aarch64-linux-gnu",
|
|
||||||
"aarch64-linux-musl",
|
|
||||||
"aarch64-windows-gnu",
|
|
||||||
"armeb-linux-gnueabi",
|
|
||||||
"armeb-linux-gnueabihf",
|
|
||||||
"armeb-linux-musleabi",
|
|
||||||
"armeb-linux-musleabihf",
|
|
||||||
"armeb-windows-gnu",
|
|
||||||
"arm-linux-gnueabi",
|
|
||||||
"arm-linux-gnueabihf",
|
|
||||||
"arm-linux-musleabi",
|
|
||||||
"arm-linux-musleabihf",
|
|
||||||
"arm-windows-gnu",
|
|
||||||
"i386-linux-gnu",
|
|
||||||
"i386-linux-musl",
|
|
||||||
"i386-windows-gnu",
|
|
||||||
"mips64el-linux-gnuabi64",
|
|
||||||
"mips64el-linux-gnuabin32",
|
|
||||||
"mips64el-linux-musl",
|
|
||||||
"mips64-linux-gnuabi64",
|
|
||||||
"mips64-linux-gnuabin32",
|
|
||||||
"mips64-linux-musl",
|
|
||||||
"mipsel-linux-gnu",
|
|
||||||
"mipsel-linux-musl",
|
|
||||||
"mips-linux-gnu",
|
|
||||||
"mips-linux-musl",
|
|
||||||
"powerpc64le-linux-gnu",
|
|
||||||
"powerpc64le-linux-musl",
|
|
||||||
"powerpc64-linux-gnu",
|
|
||||||
"powerpc64-linux-musl",
|
|
||||||
"powerpc-linux-gnu",
|
|
||||||
"powerpc-linux-musl",
|
|
||||||
"riscv64-linux-gnu",
|
|
||||||
"riscv64-linux-musl",
|
|
||||||
"s390x-linux-gnu",
|
|
||||||
"s390x-linux-musl",
|
|
||||||
"sparc-linux-gnu",
|
|
||||||
"sparcv9-linux-gnu",
|
|
||||||
"wasm32-freestanding-musl",
|
|
||||||
"x86_64-linux-gnu",
|
|
||||||
"x86_64-linux-gnux32",
|
|
||||||
"x86_64-linux-musl",
|
|
||||||
"x86_64-windows-gnu",
|
|
||||||
};
|
|
||||||
|
|
||||||
pub fn cmdTargets(
|
pub fn cmdTargets(
|
||||||
allocator: *Allocator,
|
allocator: *Allocator,
|
||||||
args: []const []const u8,
|
args: []const []const u8,
|
||||||
@ -127,9 +78,13 @@ pub fn cmdTargets(
|
|||||||
|
|
||||||
try jws.objectField("libc");
|
try jws.objectField("libc");
|
||||||
try jws.beginArray();
|
try jws.beginArray();
|
||||||
for (available_libcs) |libc| {
|
for (target.available_libcs) |libc| {
|
||||||
|
const tmp = try std.fmt.allocPrint(allocator, "{}-{}-{}", .{
|
||||||
|
@tagName(libc.arch), @tagName(libc.os), @tagName(libc.abi),
|
||||||
|
});
|
||||||
|
defer allocator.free(tmp);
|
||||||
try jws.arrayElem();
|
try jws.arrayElem();
|
||||||
try jws.emitString(libc);
|
try jws.emitString(tmp);
|
||||||
}
|
}
|
||||||
try jws.endArray();
|
try jws.endArray();
|
||||||
|
|
||||||
|
111
src-self-hosted/target.zig
Normal file
111
src-self-hosted/target.zig
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
pub const ArchOsAbi = struct {
|
||||||
|
arch: std.Target.Cpu.Arch,
|
||||||
|
os: std.Target.Os.Tag,
|
||||||
|
abi: std.Target.Abi,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const available_libcs = [_]ArchOsAbi{
|
||||||
|
.{ .arch = .aarch64_be, .os = .linux, .abi = .gnu },
|
||||||
|
.{ .arch = .aarch64_be, .os = .linux, .abi = .musl },
|
||||||
|
.{ .arch = .aarch64_be, .os = .windows, .abi = .gnu },
|
||||||
|
.{ .arch = .aarch64, .os = .linux, .abi = .gnu },
|
||||||
|
.{ .arch = .aarch64, .os = .linux, .abi = .musl },
|
||||||
|
.{ .arch = .aarch64, .os = .windows, .abi = .gnu },
|
||||||
|
.{ .arch = .armeb, .os = .linux, .abi = .gnueabi },
|
||||||
|
.{ .arch = .armeb, .os = .linux, .abi = .gnueabihf },
|
||||||
|
.{ .arch = .armeb, .os = .linux, .abi = .musleabi },
|
||||||
|
.{ .arch = .armeb, .os = .linux, .abi = .musleabihf },
|
||||||
|
.{ .arch = .armeb, .os = .windows, .abi = .gnu },
|
||||||
|
.{ .arch = .arm, .os = .linux, .abi = .gnueabi },
|
||||||
|
.{ .arch = .arm, .os = .linux, .abi = .gnueabihf },
|
||||||
|
.{ .arch = .arm, .os = .linux, .abi = .musleabi },
|
||||||
|
.{ .arch = .arm, .os = .linux, .abi = .musleabihf },
|
||||||
|
.{ .arch = .arm, .os = .windows, .abi = .gnu },
|
||||||
|
.{ .arch = .i386, .os = .linux, .abi = .gnu },
|
||||||
|
.{ .arch = .i386, .os = .linux, .abi = .musl },
|
||||||
|
.{ .arch = .i386, .os = .windows, .abi = .gnu },
|
||||||
|
.{ .arch = .mips64el, .os = .linux, .abi = .gnuabi64 },
|
||||||
|
.{ .arch = .mips64el, .os = .linux, .abi = .gnuabin32 },
|
||||||
|
.{ .arch = .mips64el, .os = .linux, .abi = .musl },
|
||||||
|
.{ .arch = .mips64, .os = .linux, .abi = .gnuabi64 },
|
||||||
|
.{ .arch = .mips64, .os = .linux, .abi = .gnuabin32 },
|
||||||
|
.{ .arch = .mips64, .os = .linux, .abi = .musl },
|
||||||
|
.{ .arch = .mipsel, .os = .linux, .abi = .gnu },
|
||||||
|
.{ .arch = .mipsel, .os = .linux, .abi = .musl },
|
||||||
|
.{ .arch = .mips, .os = .linux, .abi = .gnu },
|
||||||
|
.{ .arch = .mips, .os = .linux, .abi = .musl },
|
||||||
|
.{ .arch = .powerpc64le, .os = .linux, .abi = .gnu },
|
||||||
|
.{ .arch = .powerpc64le, .os = .linux, .abi = .musl },
|
||||||
|
.{ .arch = .powerpc64, .os = .linux, .abi = .gnu },
|
||||||
|
.{ .arch = .powerpc64, .os = .linux, .abi = .musl },
|
||||||
|
.{ .arch = .powerpc, .os = .linux, .abi = .gnu },
|
||||||
|
.{ .arch = .powerpc, .os = .linux, .abi = .musl },
|
||||||
|
.{ .arch = .riscv64, .os = .linux, .abi = .gnu },
|
||||||
|
.{ .arch = .riscv64, .os = .linux, .abi = .musl },
|
||||||
|
.{ .arch = .s390x, .os = .linux, .abi = .gnu },
|
||||||
|
.{ .arch = .s390x, .os = .linux, .abi = .musl },
|
||||||
|
.{ .arch = .sparc, .os = .linux, .abi = .gnu },
|
||||||
|
.{ .arch = .sparcv9, .os = .linux, .abi = .gnu },
|
||||||
|
.{ .arch = .wasm32, .os = .freestanding, .abi = .musl },
|
||||||
|
.{ .arch = .x86_64, .os = .linux, .abi = .gnu },
|
||||||
|
.{ .arch = .x86_64, .os = .linux, .abi = .gnux32 },
|
||||||
|
.{ .arch = .x86_64, .os = .linux, .abi = .musl },
|
||||||
|
.{ .arch = .x86_64, .os = .windows, .abi = .gnu },
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn libCGenericName(target: std.Target) [:0]const u8 {
|
||||||
|
if (target.os.tag == .windows)
|
||||||
|
return "mingw";
|
||||||
|
switch (target.abi) {
|
||||||
|
.gnu,
|
||||||
|
.gnuabin32,
|
||||||
|
.gnuabi64,
|
||||||
|
.gnueabi,
|
||||||
|
.gnueabihf,
|
||||||
|
.gnux32,
|
||||||
|
=> return "glibc",
|
||||||
|
.musl,
|
||||||
|
.musleabi,
|
||||||
|
.musleabihf,
|
||||||
|
.none,
|
||||||
|
=> return "musl",
|
||||||
|
.code16,
|
||||||
|
.eabi,
|
||||||
|
.eabihf,
|
||||||
|
.android,
|
||||||
|
.msvc,
|
||||||
|
.itanium,
|
||||||
|
.cygnus,
|
||||||
|
.coreclr,
|
||||||
|
.simulator,
|
||||||
|
.macabi,
|
||||||
|
=> unreachable,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn archMuslName(arch: std.Target.Cpu.Arch) [:0]const u8 {
|
||||||
|
switch (arch) {
|
||||||
|
.aarch64, .aarch64_be => return "aarch64",
|
||||||
|
.arm, .armeb => return "arm",
|
||||||
|
.mips, .mipsel => return "mips",
|
||||||
|
.mips64el, .mips64 => return "mips64",
|
||||||
|
.powerpc => return "powerpc",
|
||||||
|
.powerpc64, .powerpc64le => return "powerpc64",
|
||||||
|
.s390x => return "s390x",
|
||||||
|
.i386 => return "i386",
|
||||||
|
.x86_64 => return "x86_64",
|
||||||
|
.riscv64 => return "riscv64",
|
||||||
|
else => unreachable,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn canBuildLibC(target: std.Target) bool {
|
||||||
|
for (available_libcs) |libc| {
|
||||||
|
if (target.cpu.arch == libc.arch and target.os.tag == libc.os and target.abi == libc.abi) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
@ -4,6 +4,7 @@ const Module = @import("Module.zig");
|
|||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
const zir = @import("zir.zig");
|
const zir = @import("zir.zig");
|
||||||
const Package = @import("Package.zig");
|
const Package = @import("Package.zig");
|
||||||
|
const introspect = @import("introspect.zig");
|
||||||
const build_options = @import("build_options");
|
const build_options = @import("build_options");
|
||||||
const enable_qemu: bool = build_options.enable_qemu;
|
const enable_qemu: bool = build_options.enable_qemu;
|
||||||
const enable_wine: bool = build_options.enable_wine;
|
const enable_wine: bool = build_options.enable_wine;
|
||||||
@ -406,6 +407,16 @@ pub const TestContext = struct {
|
|||||||
const root_node = try progress.start("tests", self.cases.items.len);
|
const root_node = try progress.start("tests", self.cases.items.len);
|
||||||
defer root_node.end();
|
defer root_node.end();
|
||||||
|
|
||||||
|
const zig_lib_dir = try introspect.resolveZigLibDir(std.testing.allocator);
|
||||||
|
defer std.testing.allocator.free(zig_lib_dir);
|
||||||
|
|
||||||
|
const random_seed = blk: {
|
||||||
|
var random_seed: u64 = undefined;
|
||||||
|
try std.crypto.randomBytes(std.mem.asBytes(&random_seed));
|
||||||
|
break :blk random_seed;
|
||||||
|
};
|
||||||
|
var default_prng = std.rand.DefaultPrng.init(random_seed);
|
||||||
|
|
||||||
for (self.cases.items) |case| {
|
for (self.cases.items) |case| {
|
||||||
var prg_node = root_node.start(case.name, case.updates.items.len);
|
var prg_node = root_node.start(case.name, case.updates.items.len);
|
||||||
prg_node.activate();
|
prg_node.activate();
|
||||||
@ -416,11 +427,18 @@ pub const TestContext = struct {
|
|||||||
progress.initial_delay_ns = 0;
|
progress.initial_delay_ns = 0;
|
||||||
progress.refresh_rate_ns = 0;
|
progress.refresh_rate_ns = 0;
|
||||||
|
|
||||||
try self.runOneCase(std.testing.allocator, &prg_node, case);
|
try self.runOneCase(std.testing.allocator, &prg_node, case, zig_lib_dir, &default_prng.random);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn runOneCase(self: *TestContext, allocator: *Allocator, root_node: *std.Progress.Node, case: Case) !void {
|
fn runOneCase(
|
||||||
|
self: *TestContext,
|
||||||
|
allocator: *Allocator,
|
||||||
|
root_node: *std.Progress.Node,
|
||||||
|
case: Case,
|
||||||
|
zig_lib_dir: []const u8,
|
||||||
|
rand: *std.rand.Random,
|
||||||
|
) !void {
|
||||||
const target_info = try std.zig.system.NativeTargetInfo.detect(allocator, case.target);
|
const target_info = try std.zig.system.NativeTargetInfo.detect(allocator, case.target);
|
||||||
const target = target_info.target;
|
const target = target_info.target;
|
||||||
|
|
||||||
@ -438,7 +456,9 @@ pub const TestContext = struct {
|
|||||||
const ofmt: ?std.builtin.ObjectFormat = if (case.cbe) .c else null;
|
const ofmt: ?std.builtin.ObjectFormat = if (case.cbe) .c else null;
|
||||||
const bin_name = try std.zig.binNameAlloc(arena, "test_case", target, case.output_mode, null, ofmt);
|
const bin_name = try std.zig.binNameAlloc(arena, "test_case", target, case.output_mode, null, ofmt);
|
||||||
|
|
||||||
var module = try Module.init(allocator, .{
|
const module = try Module.create(allocator, .{
|
||||||
|
.zig_lib_dir = zig_lib_dir,
|
||||||
|
.rand = rand,
|
||||||
.root_name = "test_case",
|
.root_name = "test_case",
|
||||||
.target = target,
|
.target = target,
|
||||||
// TODO: support tests for object file building, and library builds
|
// TODO: support tests for object file building, and library builds
|
||||||
@ -453,7 +473,7 @@ pub const TestContext = struct {
|
|||||||
.keep_source_files_loaded = true,
|
.keep_source_files_loaded = true,
|
||||||
.object_format = ofmt,
|
.object_format = ofmt,
|
||||||
});
|
});
|
||||||
defer module.deinit();
|
defer module.destroy();
|
||||||
|
|
||||||
for (case.updates.items) |update, update_index| {
|
for (case.updates.items) |update, update_index| {
|
||||||
var update_node = root_node.start("update", 3);
|
var update_node = root_node.start("update", 3);
|
||||||
|
@ -1700,12 +1700,12 @@ const Parser = struct {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn emit(allocator: *Allocator, old_module: IrModule) !Module {
|
pub fn emit(allocator: *Allocator, old_module: *IrModule) !Module {
|
||||||
var ctx: EmitZIR = .{
|
var ctx: EmitZIR = .{
|
||||||
.allocator = allocator,
|
.allocator = allocator,
|
||||||
.decls = .{},
|
.decls = .{},
|
||||||
.arena = std.heap.ArenaAllocator.init(allocator),
|
.arena = std.heap.ArenaAllocator.init(allocator),
|
||||||
.old_module = &old_module,
|
.old_module = old_module,
|
||||||
.next_auto_name = 0,
|
.next_auto_name = 0,
|
||||||
.names = std.StringArrayHashMap(void).init(allocator),
|
.names = std.StringArrayHashMap(void).init(allocator),
|
||||||
.primitive_table = std.AutoHashMap(Inst.Primitive.Builtin, *Decl).init(allocator),
|
.primitive_table = std.AutoHashMap(Inst.Primitive.Builtin, *Decl).init(allocator),
|
||||||
@ -2539,7 +2539,7 @@ const EmitZIR = struct {
|
|||||||
return self.emitUnnamedDecl(&fntype_inst.base);
|
return self.emitUnnamedDecl(&fntype_inst.base);
|
||||||
},
|
},
|
||||||
.Int => {
|
.Int => {
|
||||||
const info = ty.intInfo(self.old_module.target());
|
const info = ty.intInfo(self.old_module.getTarget());
|
||||||
const signed = try self.emitPrimitive(src, if (info.signed) .@"true" else .@"false");
|
const signed = try self.emitPrimitive(src, if (info.signed) .@"true" else .@"false");
|
||||||
const bits_payload = try self.arena.allocator.create(Value.Payload.Int_u64);
|
const bits_payload = try self.arena.allocator.create(Value.Payload.Int_u64);
|
||||||
bits_payload.* = .{ .int = info.bits };
|
bits_payload.* = .{ .int = info.bits };
|
||||||
|
@ -78,7 +78,7 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {
|
|||||||
" -fno-emit-asm (default) do not output .s (assembly code)\n"
|
" -fno-emit-asm (default) do not output .s (assembly code)\n"
|
||||||
" -femit-llvm-ir produce a .ll file with LLVM IR\n"
|
" -femit-llvm-ir produce a .ll file with LLVM IR\n"
|
||||||
" -fno-emit-llvm-ir (default) do not produce a .ll file with LLVM IR\n"
|
" -fno-emit-llvm-ir (default) do not produce a .ll file with LLVM IR\n"
|
||||||
" -femit-h generate a C header file (.h)\n"
|
" -femit-h generate a C header file (.h)\n"
|
||||||
" -fno-emit-h (default) do not generate a C header file (.h)\n"
|
" -fno-emit-h (default) do not generate a C header file (.h)\n"
|
||||||
" --libc [file] Provide a file which specifies libc paths\n"
|
" --libc [file] Provide a file which specifies libc paths\n"
|
||||||
" --name [name] override output name\n"
|
" --name [name] override output name\n"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user