summaryrefslogtreecommitdiff
path: root/lld/wasm
diff options
context:
space:
mode:
authorSam Clegg <sbc@chromium.org>2018-01-12 22:10:35 +0000
committerSam Clegg <sbc@chromium.org>2018-01-12 22:10:35 +0000
commited1144e5cacdc381e680eb75f76043113de72889 (patch)
tree29c209ea8fa14739abec8d93ad45b34cf3acdc25 /lld/wasm
parent2f1aa3783694bb35d75fee2b1cdcab68a8356547 (diff)
[WebAssembly] Add --export flag to force a symbol to be exported
This is useful for emscripten or other tools that want to selectively exports symbols without necessarily changing the source code. Differential Revision: https://reviews.llvm.org/D42003
Diffstat (limited to 'lld/wasm')
-rw-r--r--lld/wasm/Driver.cpp17
-rw-r--r--lld/wasm/Options.td3
-rw-r--r--lld/wasm/Symbols.cpp8
-rw-r--r--lld/wasm/Symbols.h1
4 files changed, 25 insertions, 4 deletions
diff --git a/lld/wasm/Driver.cpp b/lld/wasm/Driver.cpp
index 0173cdc09e5..75c3cb56aa5 100644
--- a/lld/wasm/Driver.cpp
+++ b/lld/wasm/Driver.cpp
@@ -296,8 +296,8 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
addSyntheticUndefinedFunction(Config->Entry, &Signature);
// Handle the `--undefined <sym>` options.
- for (StringRef S : args::getStrings(Args, OPT_undefined))
- addSyntheticUndefinedFunction(S, nullptr);
+ for (auto* Arg : Args.filtered(OPT_undefined))
+ addSyntheticUndefinedFunction(Arg->getValue(), nullptr);
Config->CtorSymbol = Symtab->addDefinedFunction(
"__wasm_call_ctors", &Signature, WASM_SYMBOL_VISIBILITY_HIDDEN);
@@ -321,8 +321,8 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
// -u/--undefined since these undefined symbols have only names and no
// function signature, which means they cannot be written to the final
// output.
- for (StringRef S : args::getStrings(Args, OPT_undefined)) {
- Symbol *Sym = Symtab->find(S);
+ for (auto* Arg : Args.filtered(OPT_undefined)) {
+ Symbol *Sym = Symtab->find(Arg->getValue());
if (!Sym->isDefined())
error("function forced with --undefined not found: " + Sym->getName());
}
@@ -330,6 +330,15 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
if (errorCount())
return;
+ for (auto *Arg : Args.filtered(OPT_export)) {
+ Symbol *Sym = Symtab->find(Arg->getValue());
+ if (!Sym || !Sym->isDefined())
+ error("symbol exported via --export not found: " +
+ Twine(Arg->getValue()));
+ else
+ Sym->setHidden(false);
+ }
+
if (!Config->Entry.empty() && !Symtab->find(Config->Entry)->isDefined())
error("entry point not found: " + Config->Entry);
if (errorCount())
diff --git a/lld/wasm/Options.td b/lld/wasm/Options.td
index df0c6d70807..345417d94ae 100644
--- a/lld/wasm/Options.td
+++ b/lld/wasm/Options.td
@@ -74,6 +74,9 @@ def error_limit: J<"error-limit=">,
// The follow flags are unique to wasm
+defm export: Eq<"export">,
+ HelpText<"Force a symbol to be exported">;
+
def global_base: J<"global-base=">,
HelpText<"Where to start to place global data">;
diff --git a/lld/wasm/Symbols.cpp b/lld/wasm/Symbols.cpp
index 8376d220293..3dc88a851b3 100644
--- a/lld/wasm/Symbols.cpp
+++ b/lld/wasm/Symbols.cpp
@@ -97,6 +97,14 @@ bool Symbol::isHidden() const {
return (Flags & WASM_SYMBOL_VISIBILITY_MASK) == WASM_SYMBOL_VISIBILITY_HIDDEN;
}
+void Symbol::setHidden(bool IsHidden) {
+ Flags &= ~WASM_SYMBOL_VISIBILITY_MASK;
+ if (IsHidden)
+ Flags |= WASM_SYMBOL_VISIBILITY_HIDDEN;
+ else
+ Flags |= WASM_SYMBOL_VISIBILITY_DEFAULT;
+}
+
std::string lld::toString(const wasm::Symbol &Sym) {
if (Config->Demangle)
if (Optional<std::string> S = demangleItanium(Sym.getName()))
diff --git a/lld/wasm/Symbols.h b/lld/wasm/Symbols.h
index af06d9a5c7e..c0e71754438 100644
--- a/lld/wasm/Symbols.h
+++ b/lld/wasm/Symbols.h
@@ -67,6 +67,7 @@ public:
bool hasFunctionType() const { return FunctionType != nullptr; }
const WasmSignature &getFunctionType() const;
void setFunctionType(const WasmSignature *Type);
+ void setHidden(bool IsHidden);
uint32_t getOutputIndex() const;