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.ll
This commit is contained in:
Andrew Kelley
2020-02-18 21:59:43 -05:00
parent dba12cd693
commit d7968c6d33
8 changed files with 174 additions and 171 deletions

View File

@@ -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;