Skip to content

Commit 982575f

Browse files
authored
[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.
1 parent 95566af commit 982575f

File tree

6 files changed

+95
-11
lines changed

6 files changed

+95
-11
lines changed

lld/COFF/Config.h

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#ifndef LLD_COFF_CONFIG_H
1010
#define LLD_COFF_CONFIG_H
1111

12+
#include "lld/Common/ErrorHandler.h"
1213
#include "llvm/ADT/MapVector.h"
1314
#include "llvm/ADT/SetVector.h"
1415
#include "llvm/ADT/SmallVector.h"
@@ -27,6 +28,7 @@ namespace lld::coff {
2728
using llvm::COFF::IMAGE_FILE_MACHINE_UNKNOWN;
2829
using llvm::COFF::WindowsSubsystem;
2930
using llvm::StringRef;
31+
class COFFLinkerContext;
3032
class DefinedAbsolute;
3133
class StringChunk;
3234
class Symbol;
@@ -332,6 +334,48 @@ struct Configuration {
332334
BuildIDHash buildIDHash = BuildIDHash::None;
333335
};
334336

337+
struct COFFSyncStream : SyncStream {
338+
COFFLinkerContext &ctx;
339+
COFFSyncStream(COFFLinkerContext &ctx, DiagLevel level);
340+
};
341+
342+
template <typename T>
343+
std::enable_if_t<!std::is_pointer_v<std::remove_reference_t<T>>,
344+
const COFFSyncStream &>
345+
operator<<(const COFFSyncStream &s, T &&v) {
346+
s.os << std::forward<T>(v);
347+
return s;
348+
}
349+
350+
inline const COFFSyncStream &operator<<(const COFFSyncStream &s,
351+
const char *v) {
352+
s.os << v;
353+
return s;
354+
}
355+
356+
inline const COFFSyncStream &operator<<(const COFFSyncStream &s, Error v) {
357+
s.os << llvm::toString(std::move(v));
358+
return s;
359+
}
360+
361+
// Report a log if -verbose is specified.
362+
COFFSyncStream Log(COFFLinkerContext &ctx);
363+
364+
// Print a message to stdout.
365+
COFFSyncStream Msg(COFFLinkerContext &ctx);
366+
367+
// Report a warning. Upgraded to an error if /WX is specified.
368+
COFFSyncStream Warn(COFFLinkerContext &ctx);
369+
370+
// Report an error that will suppress the output file generation.
371+
COFFSyncStream Err(COFFLinkerContext &ctx);
372+
373+
// Report a fatal error that exits immediately. This should generally be avoided
374+
// in favor of Err.
375+
COFFSyncStream Fatal(COFFLinkerContext &ctx);
376+
377+
uint64_t errCount(COFFLinkerContext &ctx);
378+
335379
} // namespace lld::coff
336380

337381
#endif

lld/COFF/Driver.cpp

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,33 @@
5656
#include <optional>
5757
#include <tuple>
5858

59+
using namespace lld;
60+
using namespace lld::coff;
5961
using namespace llvm;
6062
using namespace llvm::object;
6163
using namespace llvm::COFF;
6264
using namespace llvm::sys;
6365

66+
COFFSyncStream::COFFSyncStream(COFFLinkerContext &ctx, DiagLevel level)
67+
: SyncStream(ctx.e, level), ctx(ctx) {}
68+
69+
COFFSyncStream coff::Log(COFFLinkerContext &ctx) {
70+
return {ctx, DiagLevel::Log};
71+
}
72+
COFFSyncStream coff::Msg(COFFLinkerContext &ctx) {
73+
return {ctx, DiagLevel::Msg};
74+
}
75+
COFFSyncStream coff::Warn(COFFLinkerContext &ctx) {
76+
return {ctx, DiagLevel::Warn};
77+
}
78+
COFFSyncStream coff::Err(COFFLinkerContext &ctx) {
79+
return {ctx, DiagLevel::Err};
80+
}
81+
COFFSyncStream coff::Fatal(COFFLinkerContext &ctx) {
82+
return {ctx, DiagLevel::Fatal};
83+
}
84+
uint64_t coff::errCount(COFFLinkerContext &ctx) { return ctx.e.errorCount; }
85+
6486
namespace lld::coff {
6587

6688
bool link(ArrayRef<const char *> args, llvm::raw_ostream &stdoutOS,
@@ -75,7 +97,7 @@ bool link(ArrayRef<const char *> args, llvm::raw_ostream &stdoutOS,
7597

7698
ctx->driver.linkerMain(args);
7799

78-
return errorCount() == 0;
100+
return errCount(*ctx) == 0;
79101
}
80102

81103
// Parse options of the form "old;new".
@@ -212,7 +234,8 @@ void LinkerDriver::addBuffer(std::unique_ptr<MemoryBuffer> mb,
212234
ctx.symtab.addFile(make<PDBInputFile>(ctx, mbref));
213235
break;
214236
case file_magic::coff_cl_gl_object:
215-
error(filename + ": is not a native COFF file. Recompile without /GL");
237+
Err(ctx) << filename
238+
<< ": is not a native COFF file. Recompile without /GL";
216239
break;
217240
case file_magic::pecoff_executable:
218241
if (ctx.config.mingw) {
@@ -302,17 +325,17 @@ void LinkerDriver::addArchiveBuffer(MemoryBufferRef mb, StringRef symName,
302325

303326
obj->parentName = parentName;
304327
ctx.symtab.addFile(obj);
305-
log("Loaded " + toString(obj) + " for " + symName);
328+
Log(ctx) << "Loaded " << obj << " for " << symName;
306329
}
307330

308331
void LinkerDriver::enqueueArchiveMember(const Archive::Child &c,
309332
const Archive::Symbol &sym,
310333
StringRef parentName) {
311334

312335
auto reportBufferError = [=](Error &&e, StringRef childName) {
313-
fatal("could not get the buffer for the member defining symbol " +
314-
toCOFFString(ctx, sym) + ": " + parentName + "(" + childName +
315-
"): " + toString(std::move(e)));
336+
Fatal(ctx) << "could not get the buffer for the member defining symbol "
337+
<< &sym << ": " << parentName << "(" << childName
338+
<< "): " << std::move(e);
316339
};
317340

318341
if (!c.getParent()->isThin()) {
@@ -361,7 +384,7 @@ void LinkerDriver::parseDirectives(InputFile *file) {
361384
if (s.empty())
362385
return;
363386

364-
log("Directives: " + toString(file) + ": " + s);
387+
Log(ctx) << "Directives: " << file << ": " << s;
365388

366389
ArgParser parser(ctx);
367390
// .drectve is always tokenized using Windows shell rules.
@@ -414,7 +437,7 @@ void LinkerDriver::parseDirectives(InputFile *file) {
414437
break;
415438
case OPT_entry:
416439
if (!arg->getValue()[0])
417-
fatal("missing entry point symbol name");
440+
Fatal(ctx) << "missing entry point symbol name";
418441
ctx.config.entry = addUndefined(mangle(arg->getValue()), true);
419442
break;
420443
case OPT_failifmismatch:
@@ -779,7 +802,7 @@ StringRef LinkerDriver::findDefaultEntry() {
779802
if (findUnderscoreMangle("wWinMain")) {
780803
if (!findUnderscoreMangle("WinMain"))
781804
return mangle("wWinMainCRTStartup");
782-
warn("found both wWinMain and WinMain; using latter");
805+
Warn(ctx) << "found both wWinMain and WinMain; using latter";
783806
}
784807
return mangle("WinMainCRTStartup");
785808
}
@@ -2200,7 +2223,7 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
22002223
config->incremental = false;
22012224
}
22022225

2203-
if (errorCount())
2226+
if (errCount(ctx))
22042227
return;
22052228

22062229
std::set<sys::fs::UniqueID> wholeArchives;
@@ -2279,7 +2302,7 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
22792302
stream << " " << path << "\n";
22802303
}
22812304

2282-
message(buffer);
2305+
Msg(ctx) << buffer;
22832306
}
22842307

22852308
// Process files specified as /defaultlib. These must be processed after

lld/COFF/InputFiles.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,11 @@ std::string lld::toString(const coff::InputFile *file) {
7070
.str();
7171
}
7272

73+
const COFFSyncStream &coff::operator<<(const COFFSyncStream &s,
74+
const InputFile *f) {
75+
return s << toString(f);
76+
}
77+
7378
/// Checks that Source is compatible with being a weak alias to Target.
7479
/// If Source is Undefined and has no weak alias set, makes it a weak
7580
/// alias to Target.

lld/COFF/InputFiles.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ class DWARFCache;
4040
namespace coff {
4141
class COFFLinkerContext;
4242

43+
const COFFSyncStream &operator<<(const COFFSyncStream &, const InputFile *);
44+
4345
std::vector<MemoryBufferRef> getArchiveMembers(llvm::object::Archive *file);
4446

4547
using llvm::COFF::IMAGE_FILE_MACHINE_UNKNOWN;

lld/COFF/Symbols.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,13 @@ std::string toCOFFString(const COFFLinkerContext &ctx,
5353
return maybeDemangleSymbol(ctx, b.getName());
5454
}
5555

56+
const COFFSyncStream &
57+
coff::operator<<(const COFFSyncStream &s,
58+
const llvm::object::Archive::Symbol *sym) {
59+
s << maybeDemangleSymbol(s.ctx, sym->getName());
60+
return s;
61+
}
62+
5663
namespace coff {
5764

5865
void Symbol::computeName() {

lld/COFF/Symbols.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ class InputFile;
3535
class ObjFile;
3636
class SymbolTable;
3737

38+
const COFFSyncStream &operator<<(const COFFSyncStream &,
39+
const llvm::object::Archive::Symbol *);
40+
3841
// The base class for real symbol classes.
3942
class Symbol {
4043
public:

0 commit comments

Comments
 (0)