improvements which allow zig to emit multiple things at once
example: zig build-obj test.zig -femit-llvm-ir -femit-asm this will generate all three: test.o test.s test.llmaster
parent
dba12cd693
commit
d7968c6d33
|
@ -1155,9 +1155,9 @@ pub const LibExeObjStep = struct {
|
|||
frameworks: BufSet,
|
||||
verbose_link: bool,
|
||||
verbose_cc: bool,
|
||||
emit_ir: bool,
|
||||
emit_asm: bool,
|
||||
emit_bin: bool,
|
||||
emit_llvm_ir: bool = false,
|
||||
emit_asm: bool = false,
|
||||
emit_bin: bool = true,
|
||||
disable_gen_h: bool,
|
||||
bundle_compiler_rt: bool,
|
||||
disable_stack_probing: bool,
|
||||
|
@ -1288,9 +1288,6 @@ pub const LibExeObjStep = struct {
|
|||
.builder = builder,
|
||||
.verbose_link = false,
|
||||
.verbose_cc = false,
|
||||
.emit_ir = false,
|
||||
.emit_asm = false,
|
||||
.emit_bin = true,
|
||||
.build_mode = builtin.Mode.Debug,
|
||||
.is_dynamic = is_dynamic,
|
||||
.kind = kind,
|
||||
|
@ -1947,9 +1944,9 @@ pub const LibExeObjStep = struct {
|
|||
if (builder.verbose_link or self.verbose_link) zig_args.append("--verbose-link") catch unreachable;
|
||||
if (builder.verbose_cc or self.verbose_cc) zig_args.append("--verbose-cc") catch unreachable;
|
||||
|
||||
try zig_args.append(if (self.emit_ir) "-femit-llvm-ir" else "-fno-emit-llvm-ir");
|
||||
try zig_args.append(if (self.emit_asm) "-femit-asm" else "-fno-emit-asm");
|
||||
try zig_args.append(if (self.emit_bin) "-femit-bin" else "-fno-emit-bin");
|
||||
if (self.emit_llvm_ir) try zig_args.append("-femit-llvm-ir");
|
||||
if (self.emit_asm) try zig_args.append("-femit-asm");
|
||||
if (!self.emit_bin) try zig_args.append("-fno-emit-bin");
|
||||
|
||||
if (self.strip) {
|
||||
try zig_args.append("--strip");
|
||||
|
|
|
@ -2136,8 +2136,10 @@ struct CodeGen {
|
|||
|
||||
Buf llvm_triple_str;
|
||||
Buf global_asm;
|
||||
Buf output_file_path;
|
||||
Buf o_file_output_path;
|
||||
Buf bin_file_output_path;
|
||||
Buf asm_file_output_path;
|
||||
Buf llvm_ir_file_output_path;
|
||||
Buf *cache_dir;
|
||||
// As an input parameter, mutually exclusive with enable_cache. But it gets
|
||||
// populated in codegen_build_and_link.
|
||||
|
@ -2198,8 +2200,6 @@ struct CodeGen {
|
|||
bool verbose_cimport;
|
||||
bool verbose_cc;
|
||||
bool verbose_llvm_cpu_features;
|
||||
bool emit_asm;
|
||||
bool emit_llvm_ir;
|
||||
bool error_during_imports;
|
||||
bool generate_error_name_table;
|
||||
bool enable_cache; // mutually exclusive with output_dir
|
||||
|
@ -2253,7 +2253,9 @@ struct CodeGen {
|
|||
bool function_sections;
|
||||
bool enable_dump_analysis;
|
||||
bool enable_doc_generation;
|
||||
bool disable_bin_generation;
|
||||
bool emit_bin;
|
||||
bool emit_asm;
|
||||
bool emit_llvm_ir;
|
||||
bool test_is_evented;
|
||||
CodeModel code_model;
|
||||
|
||||
|
|
102
src/codegen.cpp
102
src/codegen.cpp
|
@ -7915,55 +7915,49 @@ static void do_code_gen(CodeGen *g) {
|
|||
}
|
||||
}
|
||||
|
||||
void codegen_set_emit_asm(CodeGen *g, bool emit) {
|
||||
g->emit_asm = emit;
|
||||
}
|
||||
|
||||
void codegen_set_emit_llvm_ir(CodeGen *g, bool emit) {
|
||||
g->emit_llvm_ir = emit;
|
||||
}
|
||||
|
||||
static void zig_llvm_emit_output(CodeGen *g) {
|
||||
g->pass1_arena->destruct(&heap::c_allocator);
|
||||
g->pass1_arena = nullptr;
|
||||
|
||||
bool is_small = g->build_mode == BuildModeSmallRelease;
|
||||
|
||||
Buf *output_path = &g->o_file_output_path;
|
||||
char *err_msg = nullptr;
|
||||
if (!g->disable_bin_generation) {
|
||||
if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, buf_ptr(output_path),
|
||||
ZigLLVM_EmitBinary, &err_msg, g->build_mode == BuildModeDebug, is_small,
|
||||
g->enable_time_report))
|
||||
const char *asm_filename = nullptr;
|
||||
const char *bin_filename = nullptr;
|
||||
const char *llvm_ir_filename = nullptr;
|
||||
|
||||
if (g->emit_bin) bin_filename = buf_ptr(&g->o_file_output_path);
|
||||
if (g->emit_asm) asm_filename = buf_ptr(&g->asm_file_output_path);
|
||||
if (g->emit_llvm_ir) llvm_ir_filename = buf_ptr(&g->llvm_ir_file_output_path);
|
||||
|
||||
// Unfortunately, LLVM shits the bed when we ask for both binary and assembly. So we call the entire
|
||||
// pipeline multiple times if this is requested.
|
||||
if (asm_filename != nullptr && bin_filename != nullptr) {
|
||||
if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, &err_msg, g->build_mode == BuildModeDebug,
|
||||
is_small, g->enable_time_report, nullptr, bin_filename, llvm_ir_filename))
|
||||
{
|
||||
zig_panic("unable to write object file %s: %s", buf_ptr(output_path), err_msg);
|
||||
fprintf(stderr, "LLVM failed to emit file: %s\n", err_msg);
|
||||
exit(1);
|
||||
}
|
||||
validate_inline_fns(g);
|
||||
g->link_objects.append(output_path);
|
||||
if (g->bundle_compiler_rt && (g->out_type == OutTypeObj ||
|
||||
(g->out_type == OutTypeLib && !g->is_dynamic)))
|
||||
{
|
||||
bin_filename = nullptr;
|
||||
llvm_ir_filename = nullptr;
|
||||
}
|
||||
|
||||
if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, &err_msg, g->build_mode == BuildModeDebug,
|
||||
is_small, g->enable_time_report, asm_filename, bin_filename, llvm_ir_filename))
|
||||
{
|
||||
fprintf(stderr, "LLVM failed to emit file: %s\n", err_msg);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
validate_inline_fns(g);
|
||||
|
||||
if (g->emit_bin) {
|
||||
g->link_objects.append(&g->o_file_output_path);
|
||||
if (g->bundle_compiler_rt && (g->out_type == OutTypeObj || (g->out_type == OutTypeLib && !g->is_dynamic))) {
|
||||
zig_link_add_compiler_rt(g, g->sub_progress_node);
|
||||
}
|
||||
}
|
||||
if (g->emit_asm) {
|
||||
if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, buf_ptr(output_path),
|
||||
ZigLLVM_EmitAssembly, &err_msg, g->build_mode == BuildModeDebug, is_small,
|
||||
g->enable_time_report))
|
||||
{
|
||||
zig_panic("unable to write assembly file %s: %s", buf_ptr(output_path), err_msg);
|
||||
}
|
||||
validate_inline_fns(g);
|
||||
}
|
||||
if (g->emit_llvm_ir) {
|
||||
if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, buf_ptr(output_path),
|
||||
ZigLLVM_EmitLLVMIr, &err_msg, g->build_mode == BuildModeDebug, is_small,
|
||||
g->enable_time_report))
|
||||
{
|
||||
zig_panic("unable to write llvm-ir file %s: %s", buf_ptr(output_path), err_msg);
|
||||
}
|
||||
validate_inline_fns(g);
|
||||
}
|
||||
|
||||
LLVMDisposeModule(g->module);
|
||||
g->module = nullptr;
|
||||
|
@ -10446,7 +10440,9 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {
|
|||
cache_bool(ch, g->function_sections);
|
||||
cache_bool(ch, g->enable_dump_analysis);
|
||||
cache_bool(ch, g->enable_doc_generation);
|
||||
cache_bool(ch, g->disable_bin_generation);
|
||||
cache_bool(ch, g->emit_bin);
|
||||
cache_bool(ch, g->emit_llvm_ir);
|
||||
cache_bool(ch, g->emit_asm);
|
||||
cache_buf_opt(ch, g->mmacosx_version_min);
|
||||
cache_buf_opt(ch, g->mios_version_min);
|
||||
cache_usize(ch, g->version_major);
|
||||
|
@ -10491,15 +10487,15 @@ static void resolve_out_paths(CodeGen *g) {
|
|||
assert(g->output_dir != nullptr);
|
||||
assert(g->root_out_name != nullptr);
|
||||
|
||||
Buf *out_basename = buf_create_from_buf(g->root_out_name);
|
||||
Buf *o_basename = buf_create_from_buf(g->root_out_name);
|
||||
if (!g->disable_bin_generation) {
|
||||
if (g->emit_bin) {
|
||||
Buf *out_basename = buf_create_from_buf(g->root_out_name);
|
||||
Buf *o_basename = buf_create_from_buf(g->root_out_name);
|
||||
switch (g->out_type) {
|
||||
case OutTypeUnknown:
|
||||
zig_unreachable();
|
||||
case OutTypeObj:
|
||||
if (g->enable_cache && g->link_objects.length == 1 && !need_llvm_module(g)) {
|
||||
buf_init_from_buf(&g->output_file_path, g->link_objects.at(0));
|
||||
buf_init_from_buf(&g->bin_file_output_path, g->link_objects.at(0));
|
||||
return;
|
||||
}
|
||||
if (need_llvm_module(g) && g->link_objects.length != 0 && !g->enable_cache &&
|
||||
|
@ -10524,20 +10520,21 @@ static void resolve_out_paths(CodeGen *g) {
|
|||
g->version_major, g->version_minor, g->version_patch));
|
||||
break;
|
||||
}
|
||||
os_path_join(g->output_dir, o_basename, &g->o_file_output_path);
|
||||
os_path_join(g->output_dir, out_basename, &g->bin_file_output_path);
|
||||
}
|
||||
else if (g->emit_asm) {
|
||||
if (g->emit_asm) {
|
||||
Buf *asm_basename = buf_create_from_buf(g->root_out_name);
|
||||
const char *asm_ext = target_asm_file_ext(g->zig_target);
|
||||
buf_append_str(o_basename, asm_ext);
|
||||
buf_append_str(out_basename, asm_ext);
|
||||
buf_append_str(asm_basename, asm_ext);
|
||||
os_path_join(g->output_dir, asm_basename, &g->asm_file_output_path);
|
||||
}
|
||||
else if (g->emit_llvm_ir) {
|
||||
if (g->emit_llvm_ir) {
|
||||
Buf *llvm_ir_basename = buf_create_from_buf(g->root_out_name);
|
||||
const char *llvm_ir_ext = target_llvm_ir_file_ext(g->zig_target);
|
||||
buf_append_str(o_basename, llvm_ir_ext);
|
||||
buf_append_str(out_basename, llvm_ir_ext);
|
||||
buf_append_str(llvm_ir_basename, llvm_ir_ext);
|
||||
os_path_join(g->output_dir, llvm_ir_basename, &g->llvm_ir_file_output_path);
|
||||
}
|
||||
|
||||
os_path_join(g->output_dir, o_basename, &g->o_file_output_path);
|
||||
os_path_join(g->output_dir, out_basename, &g->output_file_path);
|
||||
}
|
||||
|
||||
void codegen_build_and_link(CodeGen *g) {
|
||||
|
@ -10699,7 +10696,7 @@ void codegen_build_and_link(CodeGen *g) {
|
|||
// If there is more than one object, we have to link them (with -r).
|
||||
// Finally, if we didn't make an object from zig source, and we don't have caching enabled,
|
||||
// then we have an object from C source that we must copy to the output dir which we do with a -r link.
|
||||
if (!g->disable_bin_generation &&
|
||||
if (g->emit_bin &&
|
||||
(g->out_type != OutTypeObj || g->link_objects.length > 1 ||
|
||||
(!need_llvm_module(g) && !g->enable_cache)))
|
||||
{
|
||||
|
@ -10777,6 +10774,7 @@ CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget
|
|||
Stage2LibCInstallation *libc, Buf *cache_dir, bool is_test_build, Stage2ProgressNode *progress_node)
|
||||
{
|
||||
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;
|
||||
|
||||
|
|
|
@ -26,9 +26,6 @@ void codegen_set_clang_argv(CodeGen *codegen, const char **args, size_t len);
|
|||
void codegen_set_llvm_argv(CodeGen *codegen, const char **args, size_t len);
|
||||
void codegen_set_each_lib_rpath(CodeGen *codegen, bool each_lib_rpath);
|
||||
|
||||
void codegen_set_emit_asm(CodeGen *codegen, bool emit);
|
||||
void codegen_set_emit_llvm_ir(CodeGen *codegen, bool emit);
|
||||
|
||||
void codegen_set_strip(CodeGen *codegen, bool strip);
|
||||
void codegen_set_errmsg_color(CodeGen *codegen, ErrColor err_color);
|
||||
void codegen_set_out_name(CodeGen *codegen, Buf *out_name);
|
||||
|
|
38
src/link.cpp
38
src/link.cpp
|
@ -605,7 +605,7 @@ static const char *build_libc_object(CodeGen *parent_gen, const char *name, CFil
|
|||
c_source_files.append(c_file);
|
||||
child_gen->c_source_files = c_source_files;
|
||||
codegen_build_and_link(child_gen);
|
||||
return buf_ptr(&child_gen->output_file_path);
|
||||
return buf_ptr(&child_gen->bin_file_output_path);
|
||||
}
|
||||
|
||||
static const char *path_from_zig_lib(CodeGen *g, const char *dir, const char *subpath) {
|
||||
|
@ -682,7 +682,7 @@ static const char *build_libunwind(CodeGen *parent, Stage2ProgressNode *progress
|
|||
}
|
||||
child_gen->c_source_files = c_source_files;
|
||||
codegen_build_and_link(child_gen);
|
||||
return buf_ptr(&child_gen->output_file_path);
|
||||
return buf_ptr(&child_gen->bin_file_output_path);
|
||||
}
|
||||
|
||||
static void mingw_add_cc_args(CodeGen *parent, CFile *c_file) {
|
||||
|
@ -1123,7 +1123,7 @@ static const char *build_musl(CodeGen *parent, Stage2ProgressNode *progress_node
|
|||
|
||||
child_gen->c_source_files = c_source_files;
|
||||
codegen_build_and_link(child_gen);
|
||||
return buf_ptr(&child_gen->output_file_path);
|
||||
return buf_ptr(&child_gen->bin_file_output_path);
|
||||
}
|
||||
|
||||
static void add_msvcrt_os_dep(CodeGen *parent, CodeGen *child_gen, const char *src_path) {
|
||||
|
@ -1253,7 +1253,7 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file, Stage2Pr
|
|||
child_gen->c_source_files.append(c_file);
|
||||
}
|
||||
codegen_build_and_link(child_gen);
|
||||
return buf_ptr(&child_gen->output_file_path);
|
||||
return buf_ptr(&child_gen->bin_file_output_path);
|
||||
} else if (strcmp(file, "msvcrt-os.lib") == 0) {
|
||||
CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeLib, nullptr, "msvcrt-os", progress_node);
|
||||
|
||||
|
@ -1270,7 +1270,7 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file, Stage2Pr
|
|||
}
|
||||
}
|
||||
codegen_build_and_link(child_gen);
|
||||
return buf_ptr(&child_gen->output_file_path);
|
||||
return buf_ptr(&child_gen->bin_file_output_path);
|
||||
} else if (strcmp(file, "mingwex.lib") == 0) {
|
||||
CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeLib, nullptr, "mingwex", progress_node);
|
||||
|
||||
|
@ -1295,7 +1295,7 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file, Stage2Pr
|
|||
zig_unreachable();
|
||||
}
|
||||
codegen_build_and_link(child_gen);
|
||||
return buf_ptr(&child_gen->output_file_path);
|
||||
return buf_ptr(&child_gen->bin_file_output_path);
|
||||
} else {
|
||||
zig_unreachable();
|
||||
}
|
||||
|
@ -1365,7 +1365,7 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file, Stage2Pr
|
|||
codegen_add_object(child_gen, buf_create_from_str(start_os));
|
||||
codegen_add_object(child_gen, buf_create_from_str(abi_note_o));
|
||||
codegen_build_and_link(child_gen);
|
||||
return buf_ptr(&child_gen->output_file_path);
|
||||
return buf_ptr(&child_gen->bin_file_output_path);
|
||||
} else if (strcmp(file, "libc_nonshared.a") == 0) {
|
||||
CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeLib, nullptr, "c_nonshared", progress_node);
|
||||
{
|
||||
|
@ -1445,7 +1445,7 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file, Stage2Pr
|
|||
build_libc_object(parent, deps[i].name, c_file, progress_node)));
|
||||
}
|
||||
codegen_build_and_link(child_gen);
|
||||
return buf_ptr(&child_gen->output_file_path);
|
||||
return buf_ptr(&child_gen->bin_file_output_path);
|
||||
} else {
|
||||
zig_unreachable();
|
||||
}
|
||||
|
@ -1519,7 +1519,7 @@ static Buf *build_a_raw(CodeGen *parent_gen, const char *aname, Buf *full_path,
|
|||
child_gen->want_stack_check = WantStackCheckDisabled;
|
||||
|
||||
codegen_build_and_link(child_gen);
|
||||
return &child_gen->output_file_path;
|
||||
return &child_gen->bin_file_output_path;
|
||||
}
|
||||
|
||||
static Buf *build_compiler_rt(CodeGen *parent_gen, OutType child_out_type, Stage2ProgressNode *progress_node) {
|
||||
|
@ -1681,7 +1681,7 @@ static void construct_linker_job_elf(LinkJob *lj) {
|
|||
} else if (is_dyn_lib) {
|
||||
lj->args.append("-shared");
|
||||
|
||||
assert(buf_len(&g->output_file_path) != 0);
|
||||
assert(buf_len(&g->bin_file_output_path) != 0);
|
||||
soname = buf_sprintf("lib%s.so.%" ZIG_PRI_usize, buf_ptr(g->root_out_name), g->version_major);
|
||||
}
|
||||
|
||||
|
@ -1690,7 +1690,7 @@ static void construct_linker_job_elf(LinkJob *lj) {
|
|||
}
|
||||
|
||||
lj->args.append("-o");
|
||||
lj->args.append(buf_ptr(&g->output_file_path));
|
||||
lj->args.append(buf_ptr(&g->bin_file_output_path));
|
||||
|
||||
if (lj->link_in_crt) {
|
||||
const char *crt1o;
|
||||
|
@ -1872,7 +1872,7 @@ static void construct_linker_job_wasm(LinkJob *lj) {
|
|||
}
|
||||
lj->args.append("--allow-undefined");
|
||||
lj->args.append("-o");
|
||||
lj->args.append(buf_ptr(&g->output_file_path));
|
||||
lj->args.append(buf_ptr(&g->bin_file_output_path));
|
||||
|
||||
// .o files
|
||||
for (size_t i = 0; i < g->link_objects.length; i += 1) {
|
||||
|
@ -2248,7 +2248,7 @@ static void construct_linker_job_coff(LinkJob *lj) {
|
|||
lj->args.append("-DLL");
|
||||
}
|
||||
|
||||
lj->args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(&g->output_file_path))));
|
||||
lj->args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(&g->bin_file_output_path))));
|
||||
|
||||
if (g->libc_link_lib != nullptr && g->libc != nullptr) {
|
||||
lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", g->libc->crt_dir)));
|
||||
|
@ -2501,7 +2501,7 @@ static void construct_linker_job_macho(LinkJob *lj) {
|
|||
//lj->args.append("-install_name");
|
||||
//lj->args.append(buf_ptr(dylib_install_name));
|
||||
|
||||
assert(buf_len(&g->output_file_path) != 0);
|
||||
assert(buf_len(&g->bin_file_output_path) != 0);
|
||||
}
|
||||
|
||||
lj->args.append("-arch");
|
||||
|
@ -2532,14 +2532,14 @@ static void construct_linker_job_macho(LinkJob *lj) {
|
|||
}
|
||||
|
||||
lj->args.append("-o");
|
||||
lj->args.append(buf_ptr(&g->output_file_path));
|
||||
lj->args.append(buf_ptr(&g->bin_file_output_path));
|
||||
|
||||
for (size_t i = 0; i < g->rpath_list.length; i += 1) {
|
||||
Buf *rpath = g->rpath_list.at(i);
|
||||
add_rpath(lj, rpath);
|
||||
}
|
||||
if (is_dyn_lib) {
|
||||
add_rpath(lj, &g->output_file_path);
|
||||
add_rpath(lj, &g->bin_file_output_path);
|
||||
}
|
||||
|
||||
if (is_dyn_lib) {
|
||||
|
@ -2659,14 +2659,14 @@ void codegen_link(CodeGen *g) {
|
|||
progress_name, strlen(progress_name), 0));
|
||||
}
|
||||
if (g->verbose_link) {
|
||||
fprintf(stderr, "ar rcs %s", buf_ptr(&g->output_file_path));
|
||||
fprintf(stderr, "ar rcs %s", buf_ptr(&g->bin_file_output_path));
|
||||
for (size_t i = 0; i < file_names.length; i += 1) {
|
||||
fprintf(stderr, " %s", file_names.at(i));
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
if (ZigLLVMWriteArchive(buf_ptr(&g->output_file_path), file_names.items, file_names.length, os_type)) {
|
||||
fprintf(stderr, "Unable to write archive '%s'\n", buf_ptr(&g->output_file_path));
|
||||
if (ZigLLVMWriteArchive(buf_ptr(&g->bin_file_output_path), file_names.items, file_names.length, os_type)) {
|
||||
fprintf(stderr, "Unable to write archive '%s'\n", buf_ptr(&g->bin_file_output_path));
|
||||
exit(1);
|
||||
}
|
||||
return;
|
||||
|
|
63
src/main.cpp
63
src/main.cpp
|
@ -62,17 +62,21 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {
|
|||
" -fno-stack-check disable stack probing in safe builds\n"
|
||||
" -fsanitize-c enable C undefined behavior detection in unsafe builds\n"
|
||||
" -fno-sanitize-c disable C undefined behavior detection in safe builds\n"
|
||||
" --emit [asm|bin|llvm-ir] emit a specific file format as compilation output\n"
|
||||
" --emit [asm|bin|llvm-ir] (deprecated) emit a specific file format as compilation output\n"
|
||||
" -fPIC enable Position Independent Code\n"
|
||||
" -fno-PIC disable Position Independent Code\n"
|
||||
" -ftime-report print timing diagnostics\n"
|
||||
" -fstack-report print stack size diagnostics\n"
|
||||
#ifdef ZIG_ENABLE_MEM_PROFILE
|
||||
" -fmem-report print memory usage diagnostics\n"
|
||||
#endif
|
||||
" -fdump-analysis write analysis.json file with type information\n"
|
||||
" -femit-docs create a docs/ dir with html documentation\n"
|
||||
" -fno-emit-bin skip emitting machine code\n"
|
||||
" -fno-emit-docs do not produce docs/ dir with html documentation\n"
|
||||
" -femit-bin (default) output machine code\n"
|
||||
" -fno-emit-bin do not output machine code\n"
|
||||
" -femit-asm 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"
|
||||
" -fno-emit-llvm-ir (default) do not produce a .ll file with LLVM IR\n"
|
||||
" --libc [file] Provide a file which specifies libc paths\n"
|
||||
" --name [name] override output name\n"
|
||||
" --output-dir [dir] override output directory (defaults to cwd)\n"
|
||||
|
@ -423,7 +427,7 @@ static int main0(int argc, char **argv) {
|
|||
bool stack_report = false;
|
||||
bool enable_dump_analysis = false;
|
||||
bool enable_doc_generation = false;
|
||||
bool disable_bin_generation = false;
|
||||
bool emit_bin = true;
|
||||
bool emit_asm = false;
|
||||
bool emit_llvm_ir = false;
|
||||
const char *cache_dir = nullptr;
|
||||
|
@ -553,7 +557,7 @@ static int main0(int argc, char **argv) {
|
|||
}
|
||||
|
||||
Termination term;
|
||||
args.items[0] = buf_ptr(&g->output_file_path);
|
||||
args.items[0] = buf_ptr(&g->bin_file_output_path);
|
||||
os_spawn_process(args, &term);
|
||||
if (term.how != TerminationIdClean || term.code != 0) {
|
||||
fprintf(stderr, "\nBuild failed. The following command failed:\n");
|
||||
|
@ -632,8 +636,6 @@ static int main0(int argc, char **argv) {
|
|||
enable_dump_analysis = true;
|
||||
} else if (strcmp(arg, "-femit-docs") == 0) {
|
||||
enable_doc_generation = true;
|
||||
} else if (strcmp(arg, "-fno-emit-bin") == 0) {
|
||||
disable_bin_generation = true;
|
||||
} else if (strcmp(arg, "--enable-valgrind") == 0) {
|
||||
valgrind_support = ValgrindSupportEnabled;
|
||||
} else if (strcmp(arg, "--disable-valgrind") == 0) {
|
||||
|
@ -703,9 +705,9 @@ static int main0(int argc, char **argv) {
|
|||
} else if (strcmp(arg, "--test-evented-io") == 0) {
|
||||
test_evented_io = true;
|
||||
} else if (strcmp(arg, "-femit-bin") == 0) {
|
||||
disable_bin_generation = false;
|
||||
emit_bin = true;
|
||||
} else if (strcmp(arg, "-fno-emit-bin") == 0) {
|
||||
disable_bin_generation = true;
|
||||
emit_bin = false;
|
||||
} else if (strcmp(arg, "-femit-asm") == 0) {
|
||||
emit_asm = true;
|
||||
} else if (strcmp(arg, "-fno-emit-asm") == 0) {
|
||||
|
@ -746,12 +748,12 @@ static int main0(int argc, char **argv) {
|
|||
} else if (strcmp(arg, "--emit") == 0) {
|
||||
if (strcmp(argv[i], "asm") == 0) {
|
||||
emit_asm = true;
|
||||
disable_bin_generation = true;
|
||||
emit_bin = false;
|
||||
} else if (strcmp(argv[i], "bin") == 0) {
|
||||
disable_bin_generation = false;
|
||||
emit_bin = true;
|
||||
} else if (strcmp(argv[i], "llvm-ir") == 0) {
|
||||
emit_llvm_ir = true;
|
||||
disable_bin_generation = true;
|
||||
emit_bin = false;
|
||||
} else {
|
||||
fprintf(stderr, "--emit options are 'asm', 'bin', or 'llvm-ir'\n");
|
||||
return print_error_usage(arg0);
|
||||
|
@ -1113,8 +1115,8 @@ static int main0(int argc, char **argv) {
|
|||
{
|
||||
fprintf(stderr, "Expected source file argument.\n");
|
||||
return print_error_usage(arg0);
|
||||
} else if (cmd == CmdRun && disable_bin_generation) {
|
||||
fprintf(stderr, "Cannot run non-executable file.\n");
|
||||
} else if (cmd == CmdRun && !emit_bin) {
|
||||
fprintf(stderr, "Cannot run without emitting a binary file.\n");
|
||||
return print_error_usage(arg0);
|
||||
}
|
||||
|
||||
|
@ -1191,7 +1193,10 @@ static int main0(int argc, char **argv) {
|
|||
g->enable_stack_report = stack_report;
|
||||
g->enable_dump_analysis = enable_dump_analysis;
|
||||
g->enable_doc_generation = enable_doc_generation;
|
||||
g->disable_bin_generation = disable_bin_generation;
|
||||
g->emit_bin = emit_bin;
|
||||
g->emit_asm = emit_asm;
|
||||
g->emit_llvm_ir = emit_llvm_ir;
|
||||
|
||||
codegen_set_out_name(g, buf_out_name);
|
||||
codegen_set_lib_version(g, ver_major, ver_minor, ver_patch);
|
||||
g->want_single_threaded = want_single_threaded;
|
||||
|
@ -1277,9 +1282,6 @@ static int main0(int argc, char **argv) {
|
|||
|
||||
|
||||
if (cmd == CmdBuild || cmd == CmdRun) {
|
||||
codegen_set_emit_asm(g, emit_asm);
|
||||
codegen_set_emit_llvm_ir(g, emit_llvm_ir);
|
||||
|
||||
g->enable_cache = get_cache_opt(enable_cache, cmd == CmdRun);
|
||||
codegen_build_and_link(g);
|
||||
if (root_progress_node != nullptr) {
|
||||
|
@ -1297,7 +1299,7 @@ static int main0(int argc, char **argv) {
|
|||
mem::print_report();
|
||||
#endif
|
||||
|
||||
const char *exec_path = buf_ptr(&g->output_file_path);
|
||||
const char *exec_path = buf_ptr(&g->bin_file_output_path);
|
||||
ZigList<const char*> args = {0};
|
||||
|
||||
args.append(exec_path);
|
||||
|
@ -1317,21 +1319,21 @@ static int main0(int argc, char **argv) {
|
|||
} else if (cmd == CmdBuild) {
|
||||
if (g->enable_cache) {
|
||||
#if defined(ZIG_OS_WINDOWS)
|
||||
buf_replace(&g->output_file_path, '/', '\\');
|
||||
buf_replace(&g->bin_file_output_path, '/', '\\');
|
||||
#endif
|
||||
if (final_output_dir_step != nullptr) {
|
||||
Buf *dest_basename = buf_alloc();
|
||||
os_path_split(&g->output_file_path, nullptr, dest_basename);
|
||||
os_path_split(&g->bin_file_output_path, nullptr, dest_basename);
|
||||
Buf *dest_path = buf_alloc();
|
||||
os_path_join(final_output_dir_step, dest_basename, dest_path);
|
||||
|
||||
if ((err = os_update_file(&g->output_file_path, dest_path))) {
|
||||
fprintf(stderr, "unable to copy %s to %s: %s\n", buf_ptr(&g->output_file_path),
|
||||
if ((err = os_update_file(&g->bin_file_output_path, dest_path))) {
|
||||
fprintf(stderr, "unable to copy %s to %s: %s\n", buf_ptr(&g->bin_file_output_path),
|
||||
buf_ptr(dest_path), err_str(err));
|
||||
return main_exit(root_progress_node, EXIT_FAILURE);
|
||||
}
|
||||
} else {
|
||||
if (printf("%s\n", buf_ptr(&g->output_file_path)) < 0)
|
||||
if (printf("%s\n", buf_ptr(&g->bin_file_output_path)) < 0)
|
||||
return main_exit(root_progress_node, EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
@ -1346,9 +1348,6 @@ static int main0(int argc, char **argv) {
|
|||
codegen_print_timing_report(g, stderr);
|
||||
return main_exit(root_progress_node, EXIT_SUCCESS);
|
||||
} else if (cmd == CmdTest) {
|
||||
codegen_set_emit_asm(g, emit_asm);
|
||||
codegen_set_emit_llvm_ir(g, emit_llvm_ir);
|
||||
|
||||
ZigTarget native;
|
||||
get_native_target(&native);
|
||||
|
||||
|
@ -1367,17 +1366,17 @@ static int main0(int argc, char **argv) {
|
|||
zig_print_stack_report(g, stdout);
|
||||
}
|
||||
|
||||
if (g->disable_bin_generation) {
|
||||
if (!g->emit_bin) {
|
||||
fprintf(stderr, "Semantic analysis complete. No binary produced due to -fno-emit-bin.\n");
|
||||
return main_exit(root_progress_node, EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
Buf *test_exe_path_unresolved = &g->output_file_path;
|
||||
Buf *test_exe_path_unresolved = &g->bin_file_output_path;
|
||||
Buf *test_exe_path = buf_alloc();
|
||||
*test_exe_path = os_path_resolve(&test_exe_path_unresolved, 1);
|
||||
|
||||
if (disable_bin_generation) {
|
||||
fprintf(stderr, "Created %s but skipping execution because it is non executable.\n",
|
||||
if (!g->emit_bin) {
|
||||
fprintf(stderr, "Created %s but skipping execution because no binary generated.\n",
|
||||
buf_ptr(test_exe_path));
|
||||
return main_exit(root_progress_node, EXIT_SUCCESS);
|
||||
}
|
||||
|
|
101
src/zig_llvm.cpp
101
src/zig_llvm.cpp
|
@ -161,17 +161,32 @@ unsigned ZigLLVMDataLayoutGetProgramAddressSpace(LLVMTargetDataRef TD) {
|
|||
}
|
||||
|
||||
bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMModuleRef module_ref,
|
||||
const char *filename, ZigLLVM_EmitOutputType output_type, char **error_message, bool is_debug,
|
||||
bool is_small, bool time_report)
|
||||
char **error_message, bool is_debug,
|
||||
bool is_small, bool time_report,
|
||||
const char *asm_filename, const char *bin_filename, const char *llvm_ir_filename)
|
||||
{
|
||||
TimePassesIsEnabled = time_report;
|
||||
|
||||
std::error_code EC;
|
||||
raw_fd_ostream dest(filename, EC, sys::fs::F_None);
|
||||
if (EC) {
|
||||
*error_message = strdup((const char *)StringRef(EC.message()).bytes_begin());
|
||||
return true;
|
||||
raw_fd_ostream *dest_asm = nullptr;
|
||||
raw_fd_ostream *dest_bin = nullptr;
|
||||
|
||||
if (asm_filename) {
|
||||
std::error_code EC;
|
||||
dest_asm = new(std::nothrow) raw_fd_ostream(asm_filename, EC, sys::fs::F_None);
|
||||
if (EC) {
|
||||
*error_message = strdup((const char *)StringRef(EC.message()).bytes_begin());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (bin_filename) {
|
||||
std::error_code EC;
|
||||
dest_bin = new(std::nothrow) raw_fd_ostream(bin_filename, EC, sys::fs::F_None);
|
||||
if (EC) {
|
||||
*error_message = strdup((const char *)StringRef(EC.message()).bytes_begin());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
TargetMachine* target_machine = reinterpret_cast<TargetMachine*>(targ_machine_ref);
|
||||
target_machine->setO0WantsFastISel(true);
|
||||
|
||||
|
@ -222,49 +237,51 @@ bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMM
|
|||
}
|
||||
PMBuilder->populateFunctionPassManager(FPM);
|
||||
|
||||
// Set up the per-module pass manager.
|
||||
legacy::PassManager MPM;
|
||||
MPM.add(createTargetTransformInfoWrapperPass(target_machine->getTargetIRAnalysis()));
|
||||
PMBuilder->populateModulePassManager(MPM);
|
||||
{
|
||||
// Set up the per-module pass manager.
|
||||
legacy::PassManager MPM;
|
||||
MPM.add(createTargetTransformInfoWrapperPass(target_machine->getTargetIRAnalysis()));
|
||||
PMBuilder->populateModulePassManager(MPM);
|
||||
|
||||
// Set output pass.
|
||||
TargetMachine::CodeGenFileType ft;
|
||||
if (output_type != ZigLLVM_EmitLLVMIr) {
|
||||
switch (output_type) {
|
||||
case ZigLLVM_EmitAssembly:
|
||||
ft = TargetMachine::CGFT_AssemblyFile;
|
||||
break;
|
||||
case ZigLLVM_EmitBinary:
|
||||
ft = TargetMachine::CGFT_ObjectFile;
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
// Set output passes.
|
||||
if (dest_bin) {
|
||||
if (target_machine->addPassesToEmitFile(MPM, *dest_bin, nullptr, TargetMachine::CGFT_ObjectFile)) {
|
||||
*error_message = strdup("TargetMachine can't emit an object file");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (dest_asm) {
|
||||
if (target_machine->addPassesToEmitFile(MPM, *dest_asm, nullptr, TargetMachine::CGFT_AssemblyFile)) {
|
||||
*error_message = strdup("TargetMachine can't emit an assembly file");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (target_machine->addPassesToEmitFile(MPM, dest, nullptr, ft)) {
|
||||
*error_message = strdup("TargetMachine can't emit a file of this type");
|
||||
return true;
|
||||
// run per function optimization passes
|
||||
FPM.doInitialization();
|
||||
for (Function &F : *module)
|
||||
if (!F.isDeclaration())
|
||||
FPM.run(F);
|
||||
FPM.doFinalization();
|
||||
|
||||
MPM.run(*module);
|
||||
|
||||
if (llvm_ir_filename) {
|
||||
if (LLVMPrintModuleToFile(module_ref, llvm_ir_filename, error_message)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// run per function optimization passes
|
||||
FPM.doInitialization();
|
||||
for (Function &F : *module)
|
||||
if (!F.isDeclaration())
|
||||
FPM.run(F);
|
||||
FPM.doFinalization();
|
||||
|
||||
MPM.run(*module);
|
||||
|
||||
if (output_type == ZigLLVM_EmitLLVMIr) {
|
||||
if (LLVMPrintModuleToFile(module_ref, filename, error_message)) {
|
||||
return true;
|
||||
if (time_report) {
|
||||
TimerGroup::printAll(errs());
|
||||
}
|
||||
|
||||
// MPM goes out of scope and writes to the out streams
|
||||
}
|
||||
|
||||
if (time_report) {
|
||||
TimerGroup::printAll(errs());
|
||||
}
|
||||
delete dest_asm;
|
||||
delete dest_bin;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -46,17 +46,10 @@ ZIG_EXTERN_C void ZigLLVMInitializeLowerIntrinsicsPass(LLVMPassRegistryRef R);
|
|||
ZIG_EXTERN_C char *ZigLLVMGetHostCPUName(void);
|
||||
ZIG_EXTERN_C char *ZigLLVMGetNativeFeatures(void);
|
||||
|
||||
// We use a custom enum here since LLVM does not expose LLVMIr as an emit
|
||||
// output through the same mechanism as assembly/binary.
|
||||
enum ZigLLVM_EmitOutputType {
|
||||
ZigLLVM_EmitAssembly,
|
||||
ZigLLVM_EmitBinary,
|
||||
ZigLLVM_EmitLLVMIr,
|
||||
};
|
||||
|
||||
ZIG_EXTERN_C bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMModuleRef module_ref,
|
||||
const char *filename, enum ZigLLVM_EmitOutputType output_type, char **error_message, bool is_debug,
|
||||
bool is_small, bool time_report);
|
||||
char **error_message, bool is_debug,
|
||||
bool is_small, bool time_report,
|
||||
const char *asm_filename, const char *bin_filename, const char *llvm_ir_filename);
|
||||
|
||||
ZIG_EXTERN_C LLVMTargetMachineRef ZigLLVMCreateTargetMachine(LLVMTargetRef T, const char *Triple,
|
||||
const char *CPU, const char *Features, LLVMCodeGenOptLevel Level, LLVMRelocMode Reloc,
|
||||
|
|
Loading…
Reference in New Issue