Skip to content

Add command line options and build system support for specifying LLVM target cpu and features #2595

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/all_types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1894,6 +1894,9 @@ struct CodeGen {

const char **clang_argv;
size_t clang_argv_len;

const char *llvm_cpu;
const char *llvm_features;
};

struct ZigVar {
Expand Down
41 changes: 30 additions & 11 deletions src/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8113,20 +8113,39 @@ static void init(CodeGen *g) {

const char *target_specific_cpu_args;
const char *target_specific_features;
if (g->zig_target->is_native) {
// LLVM creates invalid binaries on Windows sometimes.
// See https://github.com/ziglang/zig/issues/508
// As a workaround we do not use target native features on Windows.
if (g->zig_target->os == OsWindows || g->zig_target->os == OsUefi) {
target_specific_cpu_args = "";
target_specific_features = "";
// If the user has overridden one of either cpu or features,
// use that in place of empty string or native.
if (g->llvm_cpu != nullptr) {
target_specific_cpu_args = g->llvm_cpu;
} else {
if (g->zig_target->is_native) {
// LLVM creates invalid binaries on Windows sometimes.
// See https://github.com/ziglang/zig/issues/508
// As a workaround we do not use target native features on Windows.
if (g->zig_target->os == OsWindows || g->zig_target->os == OsUefi) {
target_specific_cpu_args = "";
} else {
target_specific_cpu_args = ZigLLVMGetHostCPUName();
}
} else {
target_specific_cpu_args = ZigLLVMGetHostCPUName();
target_specific_features = ZigLLVMGetNativeFeatures();
target_specific_cpu_args = "";
}
}
if (g->llvm_features != nullptr) {
target_specific_features = g->llvm_features;
} else {
target_specific_cpu_args = "";
target_specific_features = "";
if (g->zig_target->is_native) {
// LLVM creates invalid binaries on Windows sometimes.
// See https://github.com/ziglang/zig/issues/508
// As a workaround we do not use target native features on Windows.
if (g->zig_target->os == OsWindows || g->zig_target->os == OsUefi) {
target_specific_features = "";
} else {
target_specific_features = ZigLLVMGetNativeFeatures();
}
} else {
target_specific_features = "";
}
}

g->target_machine = LLVMCreateTargetMachine(target_ref, buf_ptr(&g->triple_str),
Expand Down
2 changes: 2 additions & 0 deletions src/link.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ static CodeGen *create_child_codegen(CodeGen *parent_gen, Buf *root_src_path, Ou
child_gen->verbose_cimport = parent_gen->verbose_cimport;
child_gen->verbose_cc = parent_gen->verbose_cc;
child_gen->llvm_argv = parent_gen->llvm_argv;
child_gen->llvm_cpu = parent_gen->llvm_cpu;
child_gen->llvm_features = parent_gen->llvm_features;
child_gen->dynamic_linker_path = parent_gen->dynamic_linker_path;

codegen_set_strip(child_gen, parent_gen->strip_debug_symbols);
Expand Down
14 changes: 12 additions & 2 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {
" -dirafter [dir] same as -isystem but do it last\n"
" -isystem [dir] add additional search path for other .h files\n"
" -mllvm [arg] forward an arg to LLVM's option processing\n"
" --llvm-cpu [cpu] set the LLVM cpu option (-mcpu)\n"
" --llvm-features [features] set the LLVM cpu features option (-mattr)\n"
" --override-std-dir [arg] use an alternate Zig standard library\n"
"\n"
"Link Options:\n"
Expand Down Expand Up @@ -450,6 +452,8 @@ int main(int argc, char **argv) {
ValgrindSupport valgrind_support = ValgrindSupportAuto;
WantPIC want_pic = WantPICAuto;
WantStackCheck want_stack_check = WantStackCheckAuto;
const char *llvm_cpu = nullptr;
const char *llvm_features = nullptr;

ZigList<const char *> llvm_argv = {0};
llvm_argv.append("zig (LLVM option parsing)");
Expand Down Expand Up @@ -745,6 +749,10 @@ int main(int argc, char **argv) {
clang_argv.append(argv[i]);

llvm_argv.append(argv[i]);
} else if (strcmp(arg, "--llvm-cpu") == 0) {
llvm_cpu = argv[i];
} else if (strcmp(arg, "--llvm-features") == 0) {
llvm_features = argv[i];
} else if (strcmp(arg, "--override-std-dir") == 0) {
override_std_dir = buf_create_from_str(argv[i]);
} else if (strcmp(arg, "--override-lib-dir") == 0) {
Expand Down Expand Up @@ -1055,9 +1063,11 @@ int main(int argc, char **argv) {
} else {
cache_dir_buf = buf_create_from_str(cache_dir);
}
CodeGen *g = codegen_create(main_pkg_path, zig_root_source_file, &target, out_type, build_mode,
override_lib_dir, override_std_dir, libc, cache_dir_buf);
CodeGen *g = codegen_create(main_pkg_path, zig_root_source_file, &target,
out_type, build_mode, override_lib_dir, override_std_dir, libc, cache_dir_buf);
if (llvm_argv.length >= 2) codegen_set_llvm_argv(g, llvm_argv.items + 1, llvm_argv.length - 2);
g->llvm_cpu = llvm_cpu;
g->llvm_features = llvm_features;
g->valgrind_support = valgrind_support;
g->want_pic = want_pic;
g->want_stack_check = want_stack_check;
Expand Down
22 changes: 22 additions & 0 deletions std/build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -965,6 +965,8 @@ pub const LibExeObjStep = struct {
name_prefix: []const u8,
filter: ?[]const u8,
single_threaded: bool,
llvm_cpu: ?[]const u8,
llvm_features: ?[]const u8,

root_src: ?[]const u8,
out_h_filename: []const u8,
Expand Down Expand Up @@ -1071,6 +1073,8 @@ pub const LibExeObjStep = struct {
.output_dir = null,
.need_system_paths = false,
.single_threaded = false,
.llvm_cpu = null,
.llvm_features = null,
};
self.computeOutFileNames();
return self;
Expand Down Expand Up @@ -1241,6 +1245,14 @@ pub const LibExeObjStep = struct {
self.disable_gen_h = value;
}

pub fn setLlvmCpu(self: *LibExeObjStep, cpu: []const u8) void {
self.llvm_cpu = cpu;
}

pub fn setLlvmFeatures(self: *LibExeObjStep, features: []const u8) void {
self.llvm_features = features;
}

/// Unless setOutputDir was called, this function must be called only in
/// the make step, from a step that has declared a dependency on this one.
/// To run an executable built with zig build, use `run`, or create an install step and invoke it.
Expand Down Expand Up @@ -1445,6 +1457,16 @@ pub const LibExeObjStep = struct {
try zig_args.append("--single-threaded");
}

if (self.llvm_cpu) |llvm_cpu| {
try zig_args.append("--llvm-cpu");
try zig_args.append(llvm_cpu);
}

if (self.llvm_features) |llvm_features| {
try zig_args.append("--llvm-features");
try zig_args.append(llvm_features);
}

switch (self.build_mode) {
builtin.Mode.Debug => {},
builtin.Mode.ReleaseSafe => zig_args.append("--release-safe") catch unreachable,
Expand Down