[lld-link] Add context-aware diagnostic functions (#118430)
Similar to #112319 for ELF. While there is some initial boilerplate, it can simplify some call sites that use Twine, especially when a printed element uses `ctx` or toString.
This commit is contained in:
@@ -9,6 +9,7 @@
|
||||
#ifndef LLD_COFF_CONFIG_H
|
||||
#define LLD_COFF_CONFIG_H
|
||||
|
||||
#include "lld/Common/ErrorHandler.h"
|
||||
#include "llvm/ADT/MapVector.h"
|
||||
#include "llvm/ADT/SetVector.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
@@ -27,6 +28,7 @@ namespace lld::coff {
|
||||
using llvm::COFF::IMAGE_FILE_MACHINE_UNKNOWN;
|
||||
using llvm::COFF::WindowsSubsystem;
|
||||
using llvm::StringRef;
|
||||
class COFFLinkerContext;
|
||||
class DefinedAbsolute;
|
||||
class StringChunk;
|
||||
class Symbol;
|
||||
@@ -332,6 +334,48 @@ struct Configuration {
|
||||
BuildIDHash buildIDHash = BuildIDHash::None;
|
||||
};
|
||||
|
||||
struct COFFSyncStream : SyncStream {
|
||||
COFFLinkerContext &ctx;
|
||||
COFFSyncStream(COFFLinkerContext &ctx, DiagLevel level);
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
std::enable_if_t<!std::is_pointer_v<std::remove_reference_t<T>>,
|
||||
const COFFSyncStream &>
|
||||
operator<<(const COFFSyncStream &s, T &&v) {
|
||||
s.os << std::forward<T>(v);
|
||||
return s;
|
||||
}
|
||||
|
||||
inline const COFFSyncStream &operator<<(const COFFSyncStream &s,
|
||||
const char *v) {
|
||||
s.os << v;
|
||||
return s;
|
||||
}
|
||||
|
||||
inline const COFFSyncStream &operator<<(const COFFSyncStream &s, Error v) {
|
||||
s.os << llvm::toString(std::move(v));
|
||||
return s;
|
||||
}
|
||||
|
||||
// Report a log if -verbose is specified.
|
||||
COFFSyncStream Log(COFFLinkerContext &ctx);
|
||||
|
||||
// Print a message to stdout.
|
||||
COFFSyncStream Msg(COFFLinkerContext &ctx);
|
||||
|
||||
// Report a warning. Upgraded to an error if /WX is specified.
|
||||
COFFSyncStream Warn(COFFLinkerContext &ctx);
|
||||
|
||||
// Report an error that will suppress the output file generation.
|
||||
COFFSyncStream Err(COFFLinkerContext &ctx);
|
||||
|
||||
// Report a fatal error that exits immediately. This should generally be avoided
|
||||
// in favor of Err.
|
||||
COFFSyncStream Fatal(COFFLinkerContext &ctx);
|
||||
|
||||
uint64_t errCount(COFFLinkerContext &ctx);
|
||||
|
||||
} // namespace lld::coff
|
||||
|
||||
#endif
|
||||
|
||||
@@ -56,11 +56,33 @@
|
||||
#include <optional>
|
||||
#include <tuple>
|
||||
|
||||
using namespace lld;
|
||||
using namespace lld::coff;
|
||||
using namespace llvm;
|
||||
using namespace llvm::object;
|
||||
using namespace llvm::COFF;
|
||||
using namespace llvm::sys;
|
||||
|
||||
COFFSyncStream::COFFSyncStream(COFFLinkerContext &ctx, DiagLevel level)
|
||||
: SyncStream(ctx.e, level), ctx(ctx) {}
|
||||
|
||||
COFFSyncStream coff::Log(COFFLinkerContext &ctx) {
|
||||
return {ctx, DiagLevel::Log};
|
||||
}
|
||||
COFFSyncStream coff::Msg(COFFLinkerContext &ctx) {
|
||||
return {ctx, DiagLevel::Msg};
|
||||
}
|
||||
COFFSyncStream coff::Warn(COFFLinkerContext &ctx) {
|
||||
return {ctx, DiagLevel::Warn};
|
||||
}
|
||||
COFFSyncStream coff::Err(COFFLinkerContext &ctx) {
|
||||
return {ctx, DiagLevel::Err};
|
||||
}
|
||||
COFFSyncStream coff::Fatal(COFFLinkerContext &ctx) {
|
||||
return {ctx, DiagLevel::Fatal};
|
||||
}
|
||||
uint64_t coff::errCount(COFFLinkerContext &ctx) { return ctx.e.errorCount; }
|
||||
|
||||
namespace lld::coff {
|
||||
|
||||
bool link(ArrayRef<const char *> args, llvm::raw_ostream &stdoutOS,
|
||||
@@ -75,7 +97,7 @@ bool link(ArrayRef<const char *> args, llvm::raw_ostream &stdoutOS,
|
||||
|
||||
ctx->driver.linkerMain(args);
|
||||
|
||||
return errorCount() == 0;
|
||||
return errCount(*ctx) == 0;
|
||||
}
|
||||
|
||||
// Parse options of the form "old;new".
|
||||
@@ -212,7 +234,8 @@ void LinkerDriver::addBuffer(std::unique_ptr<MemoryBuffer> mb,
|
||||
ctx.symtab.addFile(make<PDBInputFile>(ctx, mbref));
|
||||
break;
|
||||
case file_magic::coff_cl_gl_object:
|
||||
error(filename + ": is not a native COFF file. Recompile without /GL");
|
||||
Err(ctx) << filename
|
||||
<< ": is not a native COFF file. Recompile without /GL";
|
||||
break;
|
||||
case file_magic::pecoff_executable:
|
||||
if (ctx.config.mingw) {
|
||||
@@ -302,7 +325,7 @@ void LinkerDriver::addArchiveBuffer(MemoryBufferRef mb, StringRef symName,
|
||||
|
||||
obj->parentName = parentName;
|
||||
ctx.symtab.addFile(obj);
|
||||
log("Loaded " + toString(obj) + " for " + symName);
|
||||
Log(ctx) << "Loaded " << obj << " for " << symName;
|
||||
}
|
||||
|
||||
void LinkerDriver::enqueueArchiveMember(const Archive::Child &c,
|
||||
@@ -310,9 +333,9 @@ void LinkerDriver::enqueueArchiveMember(const Archive::Child &c,
|
||||
StringRef parentName) {
|
||||
|
||||
auto reportBufferError = [=](Error &&e, StringRef childName) {
|
||||
fatal("could not get the buffer for the member defining symbol " +
|
||||
toCOFFString(ctx, sym) + ": " + parentName + "(" + childName +
|
||||
"): " + toString(std::move(e)));
|
||||
Fatal(ctx) << "could not get the buffer for the member defining symbol "
|
||||
<< &sym << ": " << parentName << "(" << childName
|
||||
<< "): " << std::move(e);
|
||||
};
|
||||
|
||||
if (!c.getParent()->isThin()) {
|
||||
@@ -361,7 +384,7 @@ void LinkerDriver::parseDirectives(InputFile *file) {
|
||||
if (s.empty())
|
||||
return;
|
||||
|
||||
log("Directives: " + toString(file) + ": " + s);
|
||||
Log(ctx) << "Directives: " << file << ": " << s;
|
||||
|
||||
ArgParser parser(ctx);
|
||||
// .drectve is always tokenized using Windows shell rules.
|
||||
@@ -414,7 +437,7 @@ void LinkerDriver::parseDirectives(InputFile *file) {
|
||||
break;
|
||||
case OPT_entry:
|
||||
if (!arg->getValue()[0])
|
||||
fatal("missing entry point symbol name");
|
||||
Fatal(ctx) << "missing entry point symbol name";
|
||||
ctx.config.entry = addUndefined(mangle(arg->getValue()), true);
|
||||
break;
|
||||
case OPT_failifmismatch:
|
||||
@@ -779,7 +802,7 @@ StringRef LinkerDriver::findDefaultEntry() {
|
||||
if (findUnderscoreMangle("wWinMain")) {
|
||||
if (!findUnderscoreMangle("WinMain"))
|
||||
return mangle("wWinMainCRTStartup");
|
||||
warn("found both wWinMain and WinMain; using latter");
|
||||
Warn(ctx) << "found both wWinMain and WinMain; using latter";
|
||||
}
|
||||
return mangle("WinMainCRTStartup");
|
||||
}
|
||||
@@ -2200,7 +2223,7 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
|
||||
config->incremental = false;
|
||||
}
|
||||
|
||||
if (errorCount())
|
||||
if (errCount(ctx))
|
||||
return;
|
||||
|
||||
std::set<sys::fs::UniqueID> wholeArchives;
|
||||
@@ -2279,7 +2302,7 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
|
||||
stream << " " << path << "\n";
|
||||
}
|
||||
|
||||
message(buffer);
|
||||
Msg(ctx) << buffer;
|
||||
}
|
||||
|
||||
// Process files specified as /defaultlib. These must be processed after
|
||||
|
||||
@@ -70,6 +70,11 @@ std::string lld::toString(const coff::InputFile *file) {
|
||||
.str();
|
||||
}
|
||||
|
||||
const COFFSyncStream &coff::operator<<(const COFFSyncStream &s,
|
||||
const InputFile *f) {
|
||||
return s << toString(f);
|
||||
}
|
||||
|
||||
/// Checks that Source is compatible with being a weak alias to Target.
|
||||
/// If Source is Undefined and has no weak alias set, makes it a weak
|
||||
/// alias to Target.
|
||||
|
||||
@@ -40,6 +40,8 @@ class DWARFCache;
|
||||
namespace coff {
|
||||
class COFFLinkerContext;
|
||||
|
||||
const COFFSyncStream &operator<<(const COFFSyncStream &, const InputFile *);
|
||||
|
||||
std::vector<MemoryBufferRef> getArchiveMembers(llvm::object::Archive *file);
|
||||
|
||||
using llvm::COFF::IMAGE_FILE_MACHINE_UNKNOWN;
|
||||
|
||||
@@ -53,6 +53,13 @@ std::string toCOFFString(const COFFLinkerContext &ctx,
|
||||
return maybeDemangleSymbol(ctx, b.getName());
|
||||
}
|
||||
|
||||
const COFFSyncStream &
|
||||
coff::operator<<(const COFFSyncStream &s,
|
||||
const llvm::object::Archive::Symbol *sym) {
|
||||
s << maybeDemangleSymbol(s.ctx, sym->getName());
|
||||
return s;
|
||||
}
|
||||
|
||||
namespace coff {
|
||||
|
||||
void Symbol::computeName() {
|
||||
|
||||
@@ -35,6 +35,9 @@ class InputFile;
|
||||
class ObjFile;
|
||||
class SymbolTable;
|
||||
|
||||
const COFFSyncStream &operator<<(const COFFSyncStream &,
|
||||
const llvm::object::Archive::Symbol *);
|
||||
|
||||
// The base class for real symbol classes.
|
||||
class Symbol {
|
||||
public:
|
||||
|
||||
Reference in New Issue
Block a user