Skip to content

Commit a782451

Browse files
committed
Change the asserts into warning and add more test coverage
1 parent c541eee commit a782451

File tree

6 files changed

+131
-28
lines changed

6 files changed

+131
-28
lines changed

lld/COFF/Driver.cpp

Lines changed: 46 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -250,18 +250,23 @@ void LinkerDriver::addBuffer(std::unique_ptr<MemoryBuffer> mb,
250250

251251
MemoryBufferRef mbref = takeBuffer(std::move(mb));
252252

253+
auto maybePrintWarning = [&](StringRef type, StringRef message) {
254+
if (inCmdLineArchive)
255+
Warn(ctx) << type << " file provided between "
256+
<< inCmdLineArchive->startLibArg << "/"
257+
<< inCmdLineArchive->endLibArg << " " << message;
258+
};
259+
253260
// File type is detected by contents, not by file extension.
254261
switch (identify_magic(mbref.getBuffer())) {
255262
case file_magic::windows_resource:
256-
assert(!inCmdLineArchive &&
257-
"Cannot specify a RES file inside a --start-lib/--end-lib group.");
263+
maybePrintWarning(".res", "will not be lazy");
258264
resources.push_back(mbref);
259265
break;
260266
case file_magic::archive:
261267
// FIXME: We could later support --start-lib/--end-lib groups, to allow for
262268
// "extending" an existing archive/LIB.
263-
assert(!inCmdLineArchive &&
264-
"Cannot specify a LIB file inside a --start-lib/--end-lib group.");
269+
maybePrintWarning(".lib/.a", "has no effect");
265270
if (wholeArchive) {
266271
std::unique_ptr<Archive> file =
267272
CHECK(Archive::create(mbref), filename + ": failed to parse archive");
@@ -283,8 +288,7 @@ void LinkerDriver::addBuffer(std::unique_ptr<MemoryBuffer> mb,
283288
addFile(ObjFile::create(ctx, mbref), inCmdLineArchive);
284289
break;
285290
case file_magic::pdb:
286-
assert(!inCmdLineArchive &&
287-
"Cannot specify a PDB file inside a --start-lib/--end-lib group.");
291+
maybePrintWarning(".pdb", "will not be lazy");
288292
addFile(make<PDBInputFile>(ctx, mbref));
289293
break;
290294
case file_magic::coff_cl_gl_object:
@@ -293,9 +297,7 @@ void LinkerDriver::addBuffer(std::unique_ptr<MemoryBuffer> mb,
293297
break;
294298
case file_magic::pecoff_executable:
295299
if (ctx.config.mingw) {
296-
assert(
297-
!inCmdLineArchive &&
298-
"Cannot specify a PE/EXE file inside a --start-lib/--end-lib group.");
300+
maybePrintWarning(".dll", "will not be lazy");
299301
addFile(make<DLLFile>(ctx.symtab, mbref));
300302
break;
301303
}
@@ -314,7 +316,7 @@ void LinkerDriver::addBuffer(std::unique_ptr<MemoryBuffer> mb,
314316

315317
void LinkerDriver::enqueuePath(
316318
StringRef path, bool wholeArchive,
317-
std::optional<std::shared_future<CmdLineArchive *>> inCmdLineArchive) {
319+
std::optional<std::shared_ptr<CmdLineArchive *>> inCmdLineArchive) {
318320
auto future = std::make_shared<std::future<MBErrPair>>(
319321
createFutureForFile(std::string(path)));
320322
std::string pathStr = std::string(path);
@@ -354,8 +356,7 @@ void LinkerDriver::enqueuePath(
354356
Err(ctx) << msg << "; did you mean '" << nearest << "'";
355357
} else
356358
ctx.driver.addBuffer(std::move(mb), wholeArchive,
357-
inCmdLineArchive ? inCmdLineArchive->get()
358-
: nullptr);
359+
inCmdLineArchive ? **inCmdLineArchive : nullptr);
359360
});
360361
}
361362

@@ -2172,35 +2173,55 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
21722173
return false;
21732174
};
21742175

2176+
// Store start_lib/end_lib arguments in order to render dignostics in the
2177+
// same way the flags are written on the command line.
2178+
llvm::opt::Arg *startLibArg = nullptr;
2179+
llvm::opt::Arg *endLibArg = nullptr;
2180+
auto endLibSpelling = [&]() {
2181+
return endLibArg ? endLibArg->getSpelling()
2182+
: lld::args::getOptionSpellingLikeArg(
2183+
ctx.optTable, OPT_end_lib, startLibArg, ctx.saver);
2184+
};
2185+
21752186
// Create a list of input files. These can be given as OPT_INPUT options
21762187
// and OPT_wholearchive_file options, and we also need to track OPT_start_lib
21772188
// and OPT_end_lib.
21782189
{
21792190
llvm::TimeTraceScope timeScope2("Parse & queue inputs");
2180-
std::optional<std::shared_future<CmdLineArchive *>> inCmdLineArchive;
2191+
std::optional<std::shared_ptr<CmdLineArchive *>> inCmdLineArchive;
2192+
auto close = [&]() {
2193+
enqueueTask([=]() {
2194+
assert(inCmdLineArchive);
2195+
if (CmdLineArchive *a = **inCmdLineArchive)
2196+
a->maybeParse();
2197+
});
2198+
};
2199+
21812200
for (auto *arg : args) {
21822201
switch (arg->getOption().getID()) {
21832202
case OPT_end_lib:
21842203
if (!inCmdLineArchive) {
21852204
Err(ctx) << "stray " << arg->getSpelling();
21862205
} else {
2187-
enqueueTask([=]() { inCmdLineArchive->get()->maybeParse(); });
2206+
endLibArg = arg;
2207+
close();
21882208
inCmdLineArchive = std::nullopt;
21892209
}
21902210
break;
21912211
case OPT_start_lib:
21922212
if (inCmdLineArchive) {
21932213
Err(ctx) << "nested " << arg->getSpelling();
21942214
} else {
2195-
auto a = std::make_shared<std::promise<CmdLineArchive *>>();
2196-
inCmdLineArchive = a->get_future().share();
2197-
enqueueTask([&, a]() {
2215+
startLibArg = arg;
2216+
inCmdLineArchive = std::make_shared<CmdLineArchive *>();
2217+
enqueueTask([&, inCmdLineArchive, startLibArg, endLibArg]() {
21982218
// In is important to create a fake archive here so that we
21992219
// remember its placement on the command-line. This will be
22002220
// later needed to resolve symbols in the archive order required
22012221
// by the MSVC specification.
2202-
a->set_value(make<CmdLineArchive>(
2203-
ctx.symtab, MemoryBufferRef({}, "<cmdline-lib>")));
2222+
**inCmdLineArchive = make<CmdLineArchive>(
2223+
ctx.symtab, MemoryBufferRef({}, "<cmdline-lib>"),
2224+
startLibArg->getSpelling(), endLibSpelling());
22042225
});
22052226
}
22062227
break;
@@ -2218,8 +2239,11 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
22182239
}
22192240
}
22202241
if (inCmdLineArchive) {
2221-
Warn(ctx) << "--start-lib with no --end-lib";
2222-
enqueueTask([=]() { inCmdLineArchive->get()->maybeParse(); });
2242+
StringRef startLib = startLibArg->getSpelling();
2243+
Warn(ctx) << startLib << " without " << endLibSpelling()
2244+
<< "\nNOTE: all files provided after " << startLib
2245+
<< " were lazy.";
2246+
close();
22232247
}
22242248
}
22252249

@@ -2740,7 +2764,7 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
27402764
// /manifestdependency: enables /manifest unless an explicit /manifest:no is
27412765
// also passed.
27422766
if (config->manifest == Configuration::Embed)
2743-
addBuffer(createManifestRes(), false);
2767+
addBuffer(createManifestRes());
27442768
else if (config->manifest == Configuration::SideBySide ||
27452769
(config->manifest == Configuration::Default &&
27462770
!config->manifestDependencies.empty()))

lld/COFF/Driver.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ class LinkerDriver {
9595

9696
// Schedule a input file for reading.
9797
void enqueuePath(StringRef path, bool wholeArchive = false,
98-
std::optional<std::shared_future<CmdLineArchive *>>
98+
std::optional<std::shared_ptr<CmdLineArchive *>>
9999
inCmdLineArchive = std::nullopt);
100100

101101
void pullArm64ECIcallHelper();
@@ -175,7 +175,7 @@ class LinkerDriver {
175175

176176
std::set<std::string> visitedLibs;
177177

178-
void addBuffer(std::unique_ptr<MemoryBuffer> mb, bool wholeArchive,
178+
void addBuffer(std::unique_ptr<MemoryBuffer> mb, bool wholeArchive = false,
179179
CmdLineArchive *inCmdLineArchive = nullptr);
180180
void addArchiveBuffer(MemoryBufferRef mbref, StringRef symName,
181181
StringRef parentName, uint64_t offsetInArchive);

lld/COFF/InputFiles.h

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -139,17 +139,22 @@ class ArchiveFile : public InputFile {
139139
llvm::DenseSet<uint64_t> seen;
140140
};
141141

142-
// A synthetic --start-lib/--end-lib archive.
142+
// A synthetic -start-lib/-end-lib archive.
143143
class CmdLineArchive : public InputFile {
144144
public:
145-
explicit CmdLineArchive(SymbolTable &s, MemoryBufferRef m)
146-
: InputFile(s, CmdLineArchiveKind, m) {}
145+
explicit CmdLineArchive(SymbolTable &s, MemoryBufferRef m, StringRef startLib,
146+
StringRef endLib)
147+
: InputFile(s, CmdLineArchiveKind, m), startLibArg(startLib),
148+
endLibArg(endLib) {}
147149
static bool classof(const InputFile *f) {
148150
return f->kind() == CmdLineArchiveKind;
149151
}
150152
void parse() override;
151153
void addInputFile(InputFile *f);
152154

155+
StringRef startLibArg;
156+
StringRef endLibArg;
157+
153158
private:
154159
std::vector<InputFile *> files;
155160
};

lld/Common/Args.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,3 +90,13 @@ StringRef lld::args::getFilenameWithoutExe(StringRef path) {
9090
return sys::path::stem(path);
9191
return sys::path::filename(path);
9292
}
93+
94+
StringRef lld::args::getOptionSpellingLikeArg(llvm::opt::OptTable &optTable,
95+
llvm::opt::OptSpecifier opt,
96+
llvm::opt::Arg *arg,
97+
llvm::StringSaver &saver) {
98+
StringRef prefix = arg->getSpelling();
99+
prefix.consume_back(arg->getOption().getName());
100+
auto option = optTable.getOption(opt);
101+
return saver.save((prefix + option.getName()).str());
102+
}

lld/include/lld/Common/Args.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,13 @@
1515
#include <vector>
1616

1717
namespace llvm {
18+
class StringSaver;
1819
namespace opt {
20+
class Arg;
1921
class InputArgList;
20-
}
22+
class OptSpecifier;
23+
class OptTable;
24+
} // namespace opt
2125
} // namespace llvm
2226

2327
namespace lld {
@@ -40,6 +44,11 @@ std::vector<StringRef> getLines(MemoryBufferRef mb);
4044

4145
StringRef getFilenameWithoutExe(StringRef path);
4246

47+
StringRef getOptionSpellingLikeArg(llvm::opt::OptTable &optTable,
48+
llvm::opt::OptSpecifier opt,
49+
llvm::opt::Arg *arg,
50+
llvm::StringSaver &saver);
51+
4352
} // namespace args
4453
} // namespace lld
4554

lld/test/COFF/start-lib-warn.ll

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
; REQUIRES: x86
2+
;
3+
; RUN: split-file %s %t.dir
4+
;
5+
; We need an input file to lld, so create one.
6+
; RUN: llc -filetype=obj %t.dir/main.ll -o %t.obj
7+
8+
; RUN: lld-link -start-lib %t.obj /subsystem:console /force 2>&1 \
9+
; RUN: | FileCheck --check-prefix=MISSING_END %s
10+
; MISSING_END: -start-lib without -end-lib
11+
12+
; RUN: not lld-link %t.obj -end-lib /subsystem:console /force 2>&1 \
13+
; RUN: | FileCheck --check-prefix=STRAY_END %s
14+
; STRAY_END: stray -end-lib
15+
16+
; RUN: not lld-link -start-lib -start-lib %t.obj /subsystem:console /force 2>&1 \
17+
; RUN: | FileCheck --check-prefix=NESTED_START %s
18+
; NESTED_START: nested -start-lib
19+
20+
; RUN: lld-link -start-lib %t.obj %S/Inputs/resource.res -end-lib /subsystem:console /force 2>&1 \
21+
; RUN: | FileCheck --check-prefix=WARN_RES %s
22+
; WARN_RES: .res file provided between -start-lib/-end-lib will not be lazy
23+
24+
; RUN: lld-link -start-lib %t.obj %S/Inputs/ret42.lib -end-lib /subsystem:console /force 2>&1 \
25+
; RUN: | FileCheck --check-prefix=WARN_LIB %s
26+
; WARN_LIB: .lib/.a file provided between -start-lib/-end-lib has no effect
27+
28+
; RUN: lld-link -start-lib %t.obj %S/Inputs/pdb-diff-cl.pdb -end-lib /subsystem:console /force 2>&1 \
29+
; RUN: | FileCheck --check-prefix=WARN_PDB %s
30+
; WARN_PDB: .pdb file provided between -start-lib/-end-lib will not be lazy
31+
32+
; RUN: llvm-mc -filetype=obj -triple=x86_64-windows-gnu %t.dir/lib.s -o %t.lib.o
33+
; RUN: lld-link -noentry -dll -def:%t.dir/lib.def %t.lib.o -out:%t.lib.dll -implib:%t.implib.lib
34+
; RUN: lld-link -lldmingw -start-lib %t.lib.dll -end-lib /force 2>&1 \
35+
; RUN: | FileCheck --check-prefix=WARN_EXE %s
36+
; WARN_EXE: .dll file provided between -start-lib/-end-lib will not be lazy
37+
38+
#--- main.ll
39+
target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
40+
target triple = "x86_64-pc-windows-msvc"
41+
42+
define void @main() {
43+
ret void
44+
}
45+
46+
#--- lib.s
47+
.text
48+
.global func1
49+
func1:
50+
ret
51+
52+
#--- lib.def
53+
NAME lib.dll
54+
EXPORTS
55+
func1

0 commit comments

Comments
 (0)