add -femit-llvm-bc CLI option and implement it

* Added doc comments for `std.Target.ObjectFormat` enum
 * `std.Target.oFileExt` is removed because it is incorrect for Plan-9
   targets. Instead, use `std.Target.ObjectFormat.fileExt` and pass a
   CPU architecture.
 * Added `Compilation.Directory.joinZ` for when a null byte is desired.
 * Improvements to `Compilation.create` logic for computing `use_llvm`
   and reporting errors in contradictory flags. `-femit-llvm-ir` and
   `-femit-llvm-bc` will now imply `-fLLVM`.
 * Fix compilation when passing `.bc` files on the command line.
 * Improvements to the stage2 LLVM backend:
   - cleaned up error messages and error reporting. Properly bubble up
     some errors rather than dumping to stderr; others turn into panics.
   - properly call ZigLLVMCreateTargetMachine and
     ZigLLVMTargetMachineEmitToFile and implement calculation of the
     respective parameters (cpu features, code model, abi name, lto,
     tsan, etc).
   - LLVM module verification only runs in debug builds of the compiler
   - use LLVMDumpModule rather than printToString because in the case
     that we incorrectly pass a null pointer to LLVM it may crash during
     dumping the module and having it partially printed is helpful in
     this case.
   - support -femit-asm, -fno-emit-bin, -femit-llvm-ir, -femit-llvm-bc
   - Support LLVM backend when used with Mach-O and WASM linkers.
This commit is contained in:
Andrew Kelley
2021-07-22 14:44:06 -07:00
parent 36295d712f
commit a5fb28070f
20 changed files with 388 additions and 194 deletions

View File

@@ -8506,19 +8506,22 @@ static void zig_llvm_emit_output(CodeGen *g) {
const char *asm_filename = nullptr;
const char *bin_filename = nullptr;
const char *llvm_ir_filename = nullptr;
const char *bitcode_filename = nullptr;
if (buf_len(&g->o_file_output_path) != 0) bin_filename = buf_ptr(&g->o_file_output_path);
if (buf_len(&g->asm_file_output_path) != 0) asm_filename = buf_ptr(&g->asm_file_output_path);
if (buf_len(&g->llvm_ir_file_output_path) != 0) llvm_ir_filename = buf_ptr(&g->llvm_ir_file_output_path);
if (buf_len(&g->bitcode_file_output_path) != 0) bitcode_filename = buf_ptr(&g->bitcode_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.
// 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, g->tsan_enabled,
g->have_lto, nullptr, bin_filename, llvm_ir_filename))
g->have_lto, nullptr, bin_filename, llvm_ir_filename, nullptr))
{
fprintf(stderr, "LLVM failed to emit file: %s\n", err_msg);
fprintf(stderr, "LLVM failed to emit bin=%s, ir=%s: %s\n",
bin_filename, llvm_ir_filename, err_msg);
exit(1);
}
bin_filename = nullptr;
@@ -8527,9 +8530,11 @@ static void zig_llvm_emit_output(CodeGen *g) {
if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, &err_msg,
g->build_mode == BuildModeDebug, is_small, g->enable_time_report, g->tsan_enabled,
g->have_lto, asm_filename, bin_filename, llvm_ir_filename))
g->have_lto, asm_filename, bin_filename, llvm_ir_filename, bitcode_filename))
{
fprintf(stderr, "LLVM failed to emit file: %s\n", err_msg);
fprintf(stderr, "LLVM failed to emit asm=%s, bin=%s, ir=%s, bc=%s: %s\n",
asm_filename, bin_filename, llvm_ir_filename, bitcode_filename,
err_msg);
exit(1);
}