Don't output files on LLVM errors. (#4425)

Fix issue where an LLVM error or warning during IR passes (e.g. --fwarn-stack-size) does not abort outputting files. The object file would be added to the cache, and subsequent repeated LDC
execution would fetch the object file from the cache, effectively swallowing the error.
This commit is contained in:
Johan Engelen 2023-06-16 00:26:07 +02:00 committed by GitHub
parent 29bf2d302c
commit 3e2156fa68
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 62 additions and 12 deletions

View file

@ -377,15 +377,24 @@ void CodeGenerator::writeMLIRModule(mlir::OwningModuleRef *module,
const auto llpath = replaceExtensionWith(mlir_ext, filename); const auto llpath = replaceExtensionWith(mlir_ext, filename);
Logger::println("Writting MLIR to %s\n", llpath.c_str()); Logger::println("Writting MLIR to %s\n", llpath.c_str());
std::error_code errinfo; std::error_code errinfo;
llvm::raw_fd_ostream aos(llpath, errinfo, llvm::sys::fs::OF_None); llvm::ToolOutputFile aos(llpath, errinfo, llvm::sys::fs::OF_None);
if (aos.has_error()) { if (aos.os().has_error()) {
error(Loc(), "Cannot write MLIR file '%s': %s", llpath.c_str(), error(Loc(), "Cannot write MLIR file '%s': %s", llpath.c_str(),
errinfo.message().c_str()); errinfo.message().c_str());
fatal(); fatal();
} }
// module->print(aos); // module->print(aos);
// Terminate upon errors during the LLVM passes.
if (global.errors || global.warnings) {
Logger::println(
"Aborting because of errors/warnings during bitcode LLVM passes");
fatal();
}
aos.keep();
} }
} }

View file

@ -30,6 +30,7 @@
#include "llvm/Support/FormattedStream.h" #include "llvm/Support/FormattedStream.h"
#include "llvm/Support/Program.h" #include "llvm/Support/Program.h"
#include "llvm/Support/Path.h" #include "llvm/Support/Path.h"
#include "llvm/Support/ToolOutputFile.h"
#include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetMachine.h"
#include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/Analysis/TargetTransformInfo.h"
@ -93,7 +94,7 @@ void codegenModule(llvm::TargetMachine &Target, llvm::Module &m,
} }
std::error_code errinfo; std::error_code errinfo;
llvm::raw_fd_ostream out(filename, errinfo, llvm::sys::fs::OF_None); llvm::ToolOutputFile out(filename, errinfo, llvm::sys::fs::OF_None);
if (errinfo) { if (errinfo) {
error(Loc(), "cannot write file '%s': %s", filename, error(Loc(), "cannot write file '%s': %s", filename,
errinfo.message().c_str()); errinfo.message().c_str());
@ -119,7 +120,7 @@ void codegenModule(llvm::TargetMachine &Target, llvm::Module &m,
if (Target.addPassesToEmitFile( if (Target.addPassesToEmitFile(
Passes, Passes,
out, // Output file out.os(), // Output file
nullptr, // DWO output file nullptr, // DWO output file
// Always generate assembly for ptx as it is an assembly format // Always generate assembly for ptx as it is an assembly format
// The PTX backend fails if we pass anything else. // The PTX backend fails if we pass anything else.
@ -129,6 +130,14 @@ void codegenModule(llvm::TargetMachine &Target, llvm::Module &m,
} }
Passes.run(m); Passes.run(m);
// Terminate upon errors during the LLVM passes.
if (global.errors || global.warnings) {
Logger::println("Aborting because of errors/warnings during LLVM passes");
fatal();
}
out.keep();
} }
} }
@ -349,6 +358,15 @@ void writeModule(llvm::Module *m, const char *filename) {
runDLLImportRelocationPass(*gTargetMachine, *m); runDLLImportRelocationPass(*gTargetMachine, *m);
} }
// Check if there are any errors before writing files.
// Note: LLVM passes can add new warnings/errors (warnings become errors with
// `-w`) such that we reach here with errors that did not trigger earlier
// termination of the compiler.
if (global.errors) {
Logger::println("Aborting because of errors");
fatal();
}
// Everything beyond this point is writing file(s) to disk. // Everything beyond this point is writing file(s) to disk.
::TimeTraceScope timeScope("Write file(s)", filename); ::TimeTraceScope timeScope("Write file(s)", filename);
@ -371,8 +389,8 @@ void writeModule(llvm::Module *m, const char *filename) {
: replaceExtensionWith(bc_ext, filename); : replaceExtensionWith(bc_ext, filename);
Logger::println("Writing LLVM bitcode to: %s\n", bcpath.c_str()); Logger::println("Writing LLVM bitcode to: %s\n", bcpath.c_str());
std::error_code errinfo; std::error_code errinfo;
llvm::raw_fd_ostream bos(bcpath.c_str(), errinfo, llvm::sys::fs::OF_None); llvm::ToolOutputFile bos(bcpath.c_str(), errinfo, llvm::sys::fs::OF_None);
if (bos.has_error()) { if (bos.os().has_error()) {
error(Loc(), "cannot write LLVM bitcode file '%s': %s", bcpath.c_str(), error(Loc(), "cannot write LLVM bitcode file '%s': %s", bcpath.c_str(),
errinfo.message().c_str()); errinfo.message().c_str());
fatal(); fatal();
@ -390,11 +408,20 @@ void writeModule(llvm::Module *m, const char *filename) {
auto moduleSummaryIndex = buildModuleSummaryIndex( auto moduleSummaryIndex = buildModuleSummaryIndex(
*m, /* function freq callback */ nullptr, &PSI); *m, /* function freq callback */ nullptr, &PSI);
llvm::WriteBitcodeToFile(M, bos, true, &moduleSummaryIndex, llvm::WriteBitcodeToFile(M, bos.os(), true, &moduleSummaryIndex,
/* generate ThinLTO hash */ true); /* generate ThinLTO hash */ true);
} else { } else {
llvm::WriteBitcodeToFile(M, bos); llvm::WriteBitcodeToFile(M, bos.os());
} }
// Terminate upon errors during the LLVM passes.
if (global.errors || global.warnings) {
Logger::println(
"Aborting because of errors/warnings during bitcode LLVM passes");
fatal();
}
bos.keep();
} }
// write LLVM IR // write LLVM IR
@ -402,14 +429,22 @@ void writeModule(llvm::Module *m, const char *filename) {
const auto llpath = replaceExtensionWith(ll_ext, filename); const auto llpath = replaceExtensionWith(ll_ext, filename);
Logger::println("Writing LLVM IR to: %s\n", llpath.c_str()); Logger::println("Writing LLVM IR to: %s\n", llpath.c_str());
std::error_code errinfo; std::error_code errinfo;
llvm::raw_fd_ostream aos(llpath.c_str(), errinfo, llvm::sys::fs::OF_None); llvm::ToolOutputFile aos(llpath.c_str(), errinfo, llvm::sys::fs::OF_None);
if (aos.has_error()) { if (aos.os().has_error()) {
error(Loc(), "cannot write LLVM IR file '%s': %s", llpath.c_str(), error(Loc(), "cannot write LLVM IR file '%s': %s", llpath.c_str(),
errinfo.message().c_str()); errinfo.message().c_str());
fatal(); fatal();
} }
AssemblyAnnotator annotator(m->getDataLayout()); AssemblyAnnotator annotator(m->getDataLayout());
m->print(aos, &annotator); m->print(aos.os(), &annotator);
// Terminate upon errors during the LLVM passes.
if (global.errors || global.warnings) {
Logger::println("Aborting because of errors/warnings during LLVM passes");
fatal();
}
aos.keep();
} }
const bool writeObj = outputObj && !emitBitcodeAsObjectFile; const bool writeObj = outputObj && !emitBitcodeAsObjectFile;

View file

@ -7,6 +7,12 @@
// RUN: not %ldc -w -c --fwarn-stack-size=200 %s 2>&1 | FileCheck %s // RUN: not %ldc -w -c --fwarn-stack-size=200 %s 2>&1 | FileCheck %s
// Test that IR caching does not hide the warning-error in a second compilation run
// RUN: not %ldc -cache=%t-dir -w -c --fwarn-stack-size=200 %s 2>&1 | FileCheck %s
// RUN: not %ldc -cache=%t-dir -w -c --fwarn-stack-size=200 %s 2>&1 | FileCheck %s
// Test that indeed the IR cache does not exist
// RUN: not %prunecache -f %t-dir --max-bytes=1
module fwarnstacksize; module fwarnstacksize;
void small_stack() void small_stack()