Skip to content

Commit 8874104

Browse files
committed
Add allow-multiple-definition and noinhibit-exec flags to wasm-ld to enable duplicated definitions.
1 parent 8431170 commit 8874104

File tree

6 files changed

+85
-4
lines changed

6 files changed

+85
-4
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
.hidden foo
2+
.globl foo
3+
foo:
4+
.functype foo () -> (i32)
5+
i32.const 1
6+
end_function
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown %s -o %t1
2+
# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown %p/Inputs/allow-multiple-definition.s -o %t2
3+
# RUN: not wasm-ld %t1 %t2 -o /dev/null
4+
# RUN: not wasm-ld --allow-multiple-definition --no-allow-multiple-definition %t1 %t2 -o /dev/null
5+
# RUN: wasm-ld --allow-multiple-definition --fatal-warnings %t1 %t2 -o %t3
6+
# RUN: wasm-ld --allow-multiple-definition --fatal-warnings %t2 %t1 -o %t4
7+
# RUN: llvm-objdump --no-print-imm-hex -d %t3 | FileCheck %s
8+
# RUN: llvm-objdump --no-print-imm-hex -d %t4 | FileCheck --check-prefix=REVERT %s
9+
10+
# RUN: wasm-ld --noinhibit-exec %t2 %t1 -o /dev/null 2>&1 | FileCheck %s --check-prefix=WARN
11+
# WARN: warning: duplicate symbol: foo
12+
13+
# RUN: wasm-ld -z muldefs --fatal-warnings %t1 %t2 -o %t3
14+
# RUN: wasm-ld -z muldefs --fatal-warnings %t2 %t1 -o %t4
15+
# RUN: llvm-objdump --no-print-imm-hex -d %t3 | FileCheck %s
16+
# RUN: llvm-objdump --no-print-imm-hex -d %t4 | FileCheck --check-prefix=REVERT %s
17+
18+
# CHECK: i32.const 0
19+
# REVERT: i32.const 1
20+
21+
# inputs contain different constants for function foo return.
22+
# Tests below checks that order of files in command line
23+
# affects on what symbol will be used.
24+
# If flag allow-multiple-definition is enabled the first
25+
# meet symbol should be used.
26+
27+
.hidden foo
28+
.globl foo
29+
foo:
30+
.functype foo () -> (i32)
31+
i32.const 0
32+
end_function
33+
34+
.globl _start
35+
_start:
36+
.functype _start () -> (i32)
37+
call foo
38+
end_function

lld/wasm/Config.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "llvm/ADT/SmallVector.h"
1313
#include "llvm/ADT/StringRef.h"
1414
#include "llvm/ADT/StringSet.h"
15+
#include "llvm/ADT/Twine.h"
1516
#include "llvm/BinaryFormat/Wasm.h"
1617
#include "llvm/Support/CachePruning.h"
1718
#include <optional>
@@ -43,6 +44,7 @@ enum class BuildIdKind { None, Fast, Sha1, Hexstring, Uuid };
4344
// and such fields have the same name as the corresponding options.
4445
// Most fields are initialized by the driver.
4546
struct Configuration {
47+
bool allowMultipleDefinition;
4648
bool bsymbolic;
4749
bool checkFeatures;
4850
bool compressRelocations;
@@ -64,6 +66,7 @@ struct Configuration {
6466
bool importUndefined;
6567
std::optional<bool> is64;
6668
bool mergeDataSegments;
69+
bool noinhibitExec;
6770
bool pie;
6871
bool printGcSections;
6972
bool relocatable;
@@ -147,6 +150,8 @@ struct Ctx {
147150

148151
extern Ctx ctx;
149152

153+
void errorOrWarn(const llvm::Twine &msg);
154+
150155
} // namespace lld::wasm
151156

152157
#endif

lld/wasm/Driver.cpp

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,13 @@ namespace lld::wasm {
4747
Configuration *config;
4848
Ctx ctx;
4949

50+
void errorOrWarn(const llvm::Twine &msg) {
51+
if (config->noinhibitExec)
52+
warn(msg);
53+
else
54+
error(msg);
55+
}
56+
5057
void Ctx::reset() {
5158
objectFiles.clear();
5259
stubFiles.clear();
@@ -99,6 +106,16 @@ class LinkerDriver {
99106

100107
std::vector<InputFile *> files;
101108
};
109+
110+
static bool hasZOption(opt::InputArgList &args, StringRef key) {
111+
bool ret = false;
112+
for (const auto *arg : args.filtered(OPT_z))
113+
if (key == arg->getValue()) {
114+
ret = true;
115+
arg->claim();
116+
}
117+
return ret;
118+
}
102119
} // anonymous namespace
103120

104121
bool link(ArrayRef<const char *> args, llvm::raw_ostream &stdoutOS,
@@ -467,6 +484,10 @@ getBuildId(opt::InputArgList &args) {
467484

468485
// Initializes Config members by the command line options.
469486
static void readConfigs(opt::InputArgList &args) {
487+
config->allowMultipleDefinition =
488+
hasZOption(args, "muldefs") ||
489+
args.hasFlag(OPT_allow_multiple_definition,
490+
OPT_no_allow_multiple_definition, false);
470491
config->bsymbolic = args.hasArg(OPT_Bsymbolic);
471492
config->checkFeatures =
472493
args.hasFlag(OPT_check_features, OPT_no_check_features, true);
@@ -479,6 +500,7 @@ static void readConfigs(opt::InputArgList &args) {
479500
config->exportAll = args.hasArg(OPT_export_all);
480501
config->exportTable = args.hasArg(OPT_export_table);
481502
config->growableTable = args.hasArg(OPT_growable_table);
503+
config->noinhibitExec = args.hasArg(OPT_noinhibit_exec);
482504

483505
if (args.hasArg(OPT_import_memory_with_name)) {
484506
config->memoryImport =
@@ -1161,7 +1183,7 @@ static void splitSections() {
11611183

11621184
static bool isKnownZFlag(StringRef s) {
11631185
// For now, we only support a very limited set of -z flags
1164-
return s.starts_with("stack-size=");
1186+
return s.starts_with("stack-size=") || s.starts_with("muldefs");
11651187
}
11661188

11671189
// Report a warning for an unknown -z option.

lld/wasm/Options.td

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ def Bdynamic: F<"Bdynamic">, HelpText<"Link against shared libraries">;
4242

4343
def Bstatic: F<"Bstatic">, HelpText<"Do not link against shared libraries (default)">;
4444

45+
defm allow_multiple_definition: B<"allow-multiple-definition",
46+
"Allow multiple definitions",
47+
"Do not allow multiple definitions (default)">;
48+
4549
def build_id: F<"build-id">, HelpText<"Alias for --build-id=fast">;
4650

4751
def build_id_eq: J<"build-id=">, HelpText<"Generate build ID note">,
@@ -106,6 +110,9 @@ defm Map: Eq<"Map", "Print a link map to the specified file">;
106110

107111
def no_fatal_warnings: F<"no-fatal-warnings">;
108112

113+
def noinhibit_exec: F<"noinhibit-exec">,
114+
HelpText<"Retain the executable output file whenever it is still usable">;
115+
109116
def o: JoinedOrSeparate<["-"], "o">, MetaVarName<"<path>">,
110117
HelpText<"Path to file to write output">;
111118

lld/wasm/SymbolTable.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -310,9 +310,12 @@ static bool shouldReplace(const Symbol *existing, InputFile *newFile,
310310
}
311311

312312
// Neither symbol is week. They conflict.
313-
error("duplicate symbol: " + toString(*existing) + "\n>>> defined in " +
314-
toString(existing->getFile()) + "\n>>> defined in " +
315-
toString(newFile));
313+
if (config->allowMultipleDefinition) {
314+
return false;
315+
}
316+
errorOrWarn("duplicate symbol: " + toString(*existing) + "\n>>> defined in " +
317+
toString(existing->getFile()) + "\n>>> defined in " +
318+
toString(newFile));
316319
return true;
317320
}
318321

0 commit comments

Comments
 (0)