102 Commits

Author SHA1 Message Date
Sam Clegg
28f2fb24e1
Revert "[lld][WebAssembly] Do not relocate ABSOLUTE symbols" (#154371)
Reverts llvm/llvm-project#153763

This caused a bunch of failures on the emscripten waterfall,
specifically most of the lsan tests started failing.
2025-08-19 09:46:10 -07:00
YAMAMOTO Takashi
9247be8ca0
[lld][WebAssembly] Do not relocate ABSOLUTE symbols (#153763)
Fixes https://github.com/llvm/llvm-project/issues/153759
2025-08-18 21:56:48 -07:00
Nick Fitzgerald
463b3cb93f
[lld][WebAssembly] Abide by configured page size for memory imports (#146916)
This was an oversight in
https://github.com/llvm/llvm-project/pull/128942 where I forgot to add
the configured page size to the `WasmLimits` in the import we emit when
importing a memory.

Fixes: #146713
2025-07-07 09:40:09 -07:00
Anutosh Bhat
9cbbb74d37
[wasm-ld] Refactor WasmSym from static globals to per-link context (#134970)
Towards
#https://github.com/llvm/llvm-project/issues/134809#issuecomment-2787206873

This change moves WasmSym from a static global struct to an instance
owned by Ctx, allowing it to be reset cleanly between linker runs. This
enables safe support for multiple invocations of wasm-ld within the same
process

Changes done 

- Converted WasmSym from a static struct to a regular struct with
instance members.

- Added a std::unique_ptr<WasmSym> wasmSym field inside Ctx.

- Reset wasmSym in Ctx::reset() to clear state between links.

- Replaced all WasmSym:: references with ctx.wasmSym->.

- Removed global symbol definitions from Symbols.cpp that are no longer
needed.

Clearing wasmSym in ctx.reset() ensures a clean slate for each link
invocation, preventing symbol leakage across runs—critical when using
wasm-ld/lld as a reentrant library where global state can cause subtle,
hard-to-debug errors.

---------

Co-authored-by: Vassil Vassilev <v.g.vassilev@gmail.com>
2025-04-25 07:35:00 -07:00
Nick Fitzgerald
6018930ef1
[lld][WebAssembly] Support for the custom-page-sizes WebAssembly proposal (#128942)
This commit adds support for WebAssembly's custom-page-sizes proposal to
`wasm-ld`. An overview of the proposal can be found
[here](https://github.com/WebAssembly/custom-page-sizes/blob/main/proposals/custom-page-sizes/Overview.md).
In a sentence, it allows customizing a Wasm memory's page size, enabling
Wasm to target environments with less than 64KiB of memory (the default
Wasm page size) available for Wasm memories.

This commit contains the following:

* Adds a `--page-size=N` CLI flag to `wasm-ld` for configuring the
linked Wasm binary's linear memory's page size.

* When the page size is configured to a non-default value, then the
final Wasm binary will use the encodings defined in the
custom-page-sizes proposal to declare the linear memory's page size.

* Defines a `__wasm_first_page_end` symbol, whose address points to the
first page in the Wasm linear memory, a.k.a. is the Wasm memory's page
size. This allows writing code that is compatible with any page size,
and doesn't require re-compiling its object code. At the same time,
because it just lowers to a constant rather than a memory access or
something, it enables link-time optimization.

* Adds tests for these new features.

r? @sbc100 

cc @sunfishcode
2025-03-04 09:39:30 -08:00
Hood Chatham
80ea31ccd7
[lld][WebAssembly] Add RUNTIME_PATH support to wasm-ld (#129050)
This finishes adding RPATH support for WebAssembly.

See my previous PR which added RPATH support to yaml2obj and obj2yaml:
https://github.com/llvm/llvm-project/pull/126080
See corresponding update to the WebAssembly/tool-conventions repo on
dynamic linking:
https://github.com/WebAssembly/tool-conventions/pull/246
2025-02-28 11:12:52 -08:00
Derek Schuff
9fdc38c81c
[WebAssembly][Object] Support more elem segment flags (#123427)
Some tools (e.g. Rust tooling) produce element segment descriptors with
neither
elemkind or element type descriptors, but with init exprs instead of
func indices
(this is with the flags value of 4 in

https://webassembly.github.io/spec/core/binary/modules.html#element-section).
LLVM doesn't fully model reference types or the various ways to
initialize element
segments, but we do want to correctly parse and skip over all type
sections, so
this change updates the object parser to handle that case, and refactors
for more
clarity.

The test file is updated to include one additional elem segment with a
flags value
of 4, an initializer value of (32.const 0) and an empty vector. 

Also support parsing files that export imported (undefined) functions.
2025-01-17 17:26:44 -08:00
Fangrui Song
3792b36234
[lld][WebAssembly] Replace config-> with ctx.arg.
Change the global variable reference to a member access of another
variable `ctx`. In the future, we may pass through `ctx` to functions to
eliminate global variables.

Pull Request: https://github.com/llvm/llvm-project/pull/119835
2025-01-02 17:08:18 -08:00
Dan Gohman
c3536b263f
[WebAssembly] Define call-indirect-overlong and bulk-memory-opt features (#117087)
This defines some new target features. These are subsets of existing
features that reflect implementation concerns:

- "call-indirect-overlong" - implied by "reference-types"; just the
overlong encoding for the `call_indirect` immediate, and not the actual
reference types.

- "bulk-memory-opt" - implied by "bulk-memory": just `memory.copy` and
`memory.fill`, and not the other instructions in the bulk-memory
proposal.

This is split out from https://github.com/llvm/llvm-project/pull/112035.

---------

Co-authored-by: Heejin Ahn <aheejin@gmail.com>
2024-12-02 17:08:07 -08:00
Sam Clegg
1c1fbf51b5
[lld][WebAssembly] Fix TLS-relative relocations when linking without shared memory (#116136)
TLS-relative relocations always need to be relative the TLS section
since they get added to `__tls_base` at runtime.

Without this change the tls base address was effectively being added to
the final value twice in this case.

This only effects code the is built with `-pthread` but linked without
shared memory (i.e. without threads).

Fixes: https://github.com/emscripten-core/emscripten/issues/22880
2024-11-19 14:00:37 -08:00
JOE1994
4b27b5800f [lld] Nits on uses of raw_string_ostream (NFC)
* Don't call raw_string_ostream::flush(), which is essentially a no-op.
* Strip calls to raw_string_ostream::str(), to avoid excess layer of indirection.
2024-09-15 04:23:11 -04:00
Sam Clegg
5c8fd1eece
[lld][WebAssembly] Fix use of uninitialized stack data with --wasm64 (#107780)
In the case of `--wasm64` we were setting the type of the init expression
to be 64-bit but were only setting the low 32-bits of the value (by
assigning to Int32).

Fixes: https://github.com/emscripten-core/emscripten/issues/22538
2024-09-09 09:28:08 -07:00
Sam Clegg
22b7b84860
[lld][WebAssembly] Report undefined symbols in -shared/-pie builds (#75242)
Previously we would ignore all undefined symbols when using
`-shared` or `-pie`. All undefined symbols would be treated as imports
regardless of whether those symbols we defined in any shared library.
With this change we now track symbol in shared libraries and report
undefined symbols in the main program by default.
The old behavior is still available via the
`--unresolved-symbols=import-dynamic` command line flag.

This rationale for allowing this type of breaking change is that `-pie`
and `-shared` are both still experimental will warn as such, unless
`--experimental-pic` is passed.

As part of this change the linker now models shared library symbols
via new SharedFunctionSymbol and SharedDataSymbol types.

I've also added a new `--no-shlib-sigcheck` option that bypassed the
checking of functions signature in shared libraries. This is
specifically required by emscripten the case where the imports/exports
of shared libraries have been modified by via JS type legalization (this
is only needed when targeting old JS engines where bigint is not yet
available                                         

See https://github.com/emscripten-core/emscripten/issues/18198
2024-07-12 13:26:52 -07:00
Sam Clegg
39d32b238d
[WebAssembly] Use 64-bit table when targeting wasm64 (#92042)
See https://github.com/WebAssembly/memory64/issues/51
2024-05-23 18:25:58 -07:00
Sam Clegg
3c5845703c
[lld][WebAssembly] Move input vectors from symtab to ctx. NFC (#78640)
Also convert from std::vector to SmallVector.

This matches the ELF linker where these were moved into the ctx object
in 9a572164d592e and converted to SmallVector in ba948c5a9c524b.
2024-01-18 15:53:13 -08:00
Sam Clegg
184c22dd3a
[lld][WebAssembly] Move linker global state in to context object. NFC (#78629)
See lld/ELF/Config.h
2024-01-18 15:01:21 -08:00
Sam Clegg
afe957ea95
[WebAssembly] Allow absolute symbols in the linking section (symbol table) (#67493)
Fixes a crash in `-Wl,-emit-relocs` where the linker was not able to
write linker-synthetic absolute symbols to the symbol table.

This change adds a new symbol flag (`WASM_SYMBOL_ABS`), which means that
the symbol's offset is absolute and not relative to a given segment.
Such symbols include `__stack_low` and `__stack_low`.

Note that wasm object files never contains such symbols, only binaries
linked with `-Wl,-emit-relocs`.

Fixes: #67111
2023-10-03 13:16:16 -07:00
Sam Clegg
8e44f037dc [lld][WebAssembly] Add support for -soname
This change writes the module name to the name section of the wasm
binary.  We use the `-soname` argument to determine the name and we
default the output file basename if this option is not specified.

In the future we will likely want to embed the soname in the dylink
section too, but this the first step in supporting `-soname`.

Differential Revision: https://reviews.llvm.org/D158001
2023-08-15 18:33:45 -07:00
YAMAMOTO Takashi
47ba908a5e [lld][WebAssembly] Fix func reloc for internal GOT with extended-const
Differential Revision: https://reviews.llvm.org/D155542
2023-07-27 00:46:00 -07:00
Alexandre Ganea
7adaefbaa8 [wasm] Silence 'not all control paths return a value' warning when
building with MSVC on Windows
2023-03-15 14:20:18 -04:00
Sam Clegg
d32f71a91a [lld][WebAssembly] Use C++17 nested namespace syntax in most places. NFC
Like D131405, but for wasm-ld.

Differential Revision: https://reviews.llvm.org/D145399
2023-03-09 18:37:32 -08:00
Derek Schuff
c7af9ae577 Reapply: [WebAssembly] Implement build-id feature
Implement the --build-id flag similarly to ELF, and generate a
build_id section according to the WebAssembly tool convention
specified in https://github.com/WebAssembly/tool-conventions/pull/183

The default style ("fast" aka "tree") hashes the contents of the
output and (unlike ELF) generates a v5 UUID based on the hash (using a
random namespace). It also supports generating a random v4 UUID, a
sha1 hash, and a user-specified string (as ELF does).

Differential Revision: https://reviews.llvm.org/D107662

Fix MSVC build by std::copy on the underying buffer rather than
directly from std::array to llvm::MutableArrayRef
2023-03-03 17:15:55 -08:00
Derek Schuff
c8e5354f00 Revert "[WebAssembly] Implement build-id feature"
This reverts commit 41e31466af6a7feab82742bb01af43f4f3ae4ede
due to a build failure on Windows.
2023-03-02 15:28:56 -08:00
Derek Schuff
41e31466af [WebAssembly] Implement build-id feature
Implement the --build-id flag similarly to ELF, and generate a build_id
section according to the WebAssembly tool convention specified in
https://github.com/WebAssembly/tool-conventions/pull/183

The default style ("fast" aka "tree") hashes the contents of the output
and (unlike ELF) generates a v5 UUID based on the hash (using a random
namespace).
It also supports generating a random v4 UUID, a sha1 hash,
and a user-specified string (as ELF does).

Differential Revision: https://reviews.llvm.org/D107662
2023-03-02 14:19:06 -08:00
Kazu Hirata
b9ef5648b5 [lld] Use std::optional instead of llvm::Optional (NFC)
This is part of an effort to migrate from llvm::Optional to
std::optional:

https://discourse.llvm.org/t/deprecating-llvm-optional-x-hasvalue-getvalue-getvalueor/63716
2023-01-02 18:29:04 -08:00
Guillaume Chatelet
1565317287 Revert D139181 "[lld][Alignment][NFC] Use Align instead of log2 of alignment in Wasm Sections"
As discussed on the patch the Align type is probably not a good fit for
linkers.
This reverts commit cfe77f23d6f190d54763a7575cee95aceb9216bc.
2022-12-20 10:58:56 +00:00
Fangrui Song
d88e8dcc72 [lld] llvm::Optional::value => operator*/operator->
std::optional::value() has undesired exception checking semantics and is
unavailable in some older Xcode. The call sites block std::optional migration.
2022-12-17 05:03:57 +00:00
Guillaume Chatelet
cfe77f23d6 [lld][Alignment][NFC] Use Align instead of log2 of alignment in Wasm Sections
I intend to slowly upgrade all alignments to the Align type in lld as well.
Some places talk about alignment in Bytes while other specify them as Log2(Bytes).
Let's make sure all of this is coherent.

Differential Revision: https://reviews.llvm.org/D139181
2022-12-02 12:47:41 +00:00
Florian Mayer
2390bb2347 [NFC] use has_value instead of hasValue 2022-10-31 16:43:14 -07:00
Dan Gohman
d4c8a0edca [wasm-ld] Allow importing/exporting the output module's memory with arbitrary names
This adds an `--export-memory` option to wasm-ld which allows passing
a name to give to the exported memory, and extends `--import-memory` to
allow passing a <module>,<name> pair specifying where the memory should
be imported from.

This is based on https://reviews.llvm.org/D131376, with the main
difference being that it only supports exporting memory by one name.

Differential Revision: https://reviews.llvm.org/D135898
2022-10-31 13:59:46 -07:00
Kazu Hirata
3850edd9e0 Use llvm::count_if (NFC) 2022-09-03 11:17:35 -07:00
Sam Clegg
113b568829 [lld][WebAssembly] Rename SymbolTable::getSymbols to match ELF backend. NFC
The ELF backend originally used `getSymbols()` but went though a
sequence of changes that resulted in this method being called
`symbols()`.

d8f8abbd4a2823f223bd7bc56445541fb221b512 replaced `getSymbols()` with
`forEachSymbol`.

a2fc96441788fba1e4709d63677f34ed8e321dae replaced `forEachSymbol` with
`llvm::iterator_range`.

e9262edf0d11a907763098d8e101219ccd9c43e9 replaced `llvm::iterator_range`
with `symbols()`.

Differential Revision: https://reviews.llvm.org/D131284
2022-08-31 14:33:45 -07:00
Kazu Hirata
f5a68feab3 Use llvm::none_of (NFC) 2022-08-14 16:25:39 -07:00
Kazu Hirata
757d9d22cd [lld] Use value_or instead of getValueOr (NFC) 2022-06-19 00:29:41 -07:00
Sam Clegg
87099a0438 [lld][WebAssembly] Remove unnecessary accessor methods. NFC
This is less code, and matches more closely the ELF linker.

Differential Revision: https://reviews.llvm.org/D126979
2022-06-03 11:43:44 -07:00
Martin Storsjö
46776f7556 Fix warnings about variables that are set but only used in debug mode
Add void casts to mark the variables used, next to the places where
they are used in assert or `LLVM_DEBUG()` expressions.

Differential Revision: https://reviews.llvm.org/D123117
2022-04-06 10:01:46 +03:00
Sam Clegg
4690bf2ed3 [lld][WebAssembly] Take advantage of extended const expressions when available
In particular we use these in two places:

1. When building PIC code we no longer need to combine output segments
   into a single segment that can be initialized at `__memory_base`.
   Instead each segment can encode its offset from `__memory_base` in
   its initializer.  e.g.

```
(i32.add (global.get __memory_base) (i32.const offset)
```

2. When building PIC code we no longer need to relocation internalized
   global addresses.  We can just initialize them with their correct
   offsets.

Differential Revision: https://reviews.llvm.org/D121420
2022-03-15 17:50:05 -07:00
Sam Clegg
86c90f9bfd [lld][WebAssembly] Add --unresolved-symbols=import-dynamic
This is a new mode for handling unresolved symbols that allows all
symbols to be imported in the same that they would be in the case of
`-fpie` or `-shared`, but generting an otherwise fixed/non-relocatable
binary.

Code linked in this way should still be compiled with `-fPIC` so that
data symbols can be resolved via imports.

This essentially allows the building of static binaries that have
dynamic imports.  See:
https://github.com/emscripten-core/emscripten/issues/12682

As with other uses of the experimental dynamic linking ABI, this
behaviour will produce a warning unless run with `--experimental-pic`.

Differential Revision: https://reviews.llvm.org/D91577
2022-03-15 15:10:21 -07:00
Sam Clegg
9504ab32b7 [WebAssembly] Second phase of implemented extended const proposal
This change continues to lay the ground work for supporting extended
const expressions in the linker.

The included test covers object file reading and writing and the YAML
representation.

Differential Revision: https://reviews.llvm.org/D121349
2022-03-14 08:55:47 -07:00
Sam Clegg
d2a0ef9844 [lld][WebAssembly] Don't force the export symbols assiged internal/dummy GOT entries
Symbols with regular GOT entries do need to be exported, but those that
are internalized (and have dymmy/internal GOT entries) need not be
exported.

This happens to fix the failures on the emscripten waterfall where extra
symbols were being exported by the linker (and then later removed by
wasm-opt).

Differential Revision: https://reviews.llvm.org/D119902
2022-02-15 17:29:45 -08:00
Sam Clegg
182b72aa48 [lld][WebAssembly] Generate TLS relocation code also when linking statically
Previously relocations were only generated for PIC output, but
relocations for TLS GOT entries are always needed when shared
memory is enabled, not just in PIC mode.

This means that the `__wasm_apply_global_tls_relocs` is now
generated even for statically linked (non-PIC) output.  Without
this the globals that hold the addresses of TLS symbols are
not set correctly.

Differential Revision: https://reviews.llvm.org/D112833
2021-10-29 13:26:35 -07:00
Sam Clegg
1eb79e732c [lld][WebAssembly] Initialize bss segments using memory.fill
Previously we were relying on the dynamic loader to take care of this
but it simple and correct for us to do it here instead.

Now we initialize bss segments as part of `__wasm_init_memory` at the
same time we initialize passive segments.

In addition we extent the us of `__wasm_init_memory` outside of shared
memory situations.  Specifically it is now used to initialize bss
segments when the memory is imported.

Differential Revision: https://reviews.llvm.org/D112667
2021-10-28 17:15:08 -07:00
Sam Clegg
659a08399a [WebAssembly] Add import info to dylink section of shared libraries
See https://github.com/WebAssembly/tool-conventions/pull/175

Differential Revision: https://reviews.llvm.org/D111345
2021-10-15 11:49:16 -07:00
Heejin Ahn
9261ee32dc [WebAssembly] Make EH work with dynamic linking
This makes Wasm EH work with dynamic linking. So far we were only able
to handle destructors, which do not use any tags or LSDA info.

1. This uses `TargetExternalSymbol` for `GCC_except_tableN` symbols,
   which points to the address of per-function LSDA info. It is more
   convenient to use than `MCSymbol` because it can take additional
   target flags.

2. When lowering `wasm_lsda` intrinsic, if PIC is enabled, make the
   symbol relative to `__memory_base` and generate the `add` node. If
   PIC is disabled, continue to use the absolute address.

3. Make tag symbols (`__cpp_exception` and `__c_longjmp`) undefined in
   the backend, because it is hard to make it work with dynamic
   linking's loading order. Instead, we make all tag symbols undefined
   in the LLVM backend and import it from JS.

4. Add support for undefined tags to the linker.

Companion patches:
- https://github.com/WebAssembly/binaryen/pull/4223
- https://github.com/emscripten-core/emscripten/pull/15266

Reviewed By: sbc100

Differential Revision: https://reviews.llvm.org/D111388
2021-10-12 23:28:27 -07:00
Heejin Ahn
3ec1760d91 [WebAssembly] Remove WasmTagType
This removes `WasmTagType`. `WasmTagType` contained an attribute and a
signature index:
```
struct WasmTagType {
  uint8_t Attribute;
  uint32_t SigIndex;
};
```

Currently the attribute field is not used and reserved for future use,
and always 0. And that this class contains `SigIndex` as its property is
a little weird in the place, because the tag type's signature index is
not an inherent property of a tag but rather a reference to another
section that changes after linking. This makes tag handling in the
linker also weird that tag-related methods are taking both `WasmTagType`
and `WasmSignature` even though `WasmTagType` contains a signature
index. This is because the signature index changes in linking so it
doesn't have any info at this point. This instead moves `SigIndex` to
`struct WasmTag` itself, as we did for `struct WasmFunction` in D111104.

In this CL, in lib/MC and lib/Object, this now treats tag types in the
same way as function types. Also in YAML, this removes `struct Tag`,
because now it only contains the tag index. Also tags set `SigIndex` in
`WasmImport` union, as functions do.

I think this makes things simpler and makes tag handling more in line
with function handling. These two shares similar properties in that both
of them have signatures, but they are kind of nominal so having the same
signature doesn't mean they are the same element.

Also a drive-by fix: the reserved 'attirubute' part's encoding changed
from uleb32 to uint8 a while ago. This was fixed in lib/MC and
lib/Object but not in YAML. This doesn't change object files because the
field's value is always 0 and its encoding is the same for the both
encoding.

This is effectively NFC; I didn't mark it as such just because it
changed YAML test results.

Reviewed By: sbc100, tlively

Differential Revision: https://reviews.llvm.org/D111086
2021-10-05 17:11:22 -07:00
Sam Clegg
ef8c9135ef [WebAssembly] Allow import and export of TLS symbols between DSOs
We previously had a limitation that TLS variables could not
be exported (and therefore could also not be imported).  This
change removed that limitation.

Differential Revision: https://reviews.llvm.org/D108877
2021-09-14 06:47:37 -07:00
Sam Clegg
b78c85a44a [WebAssembly] Convert to new "dylink.0" section format
This format is based on sub-sections (like the "linking" and "name"
sections) and is therefore easier to extend going forward.

spec change: https://github.com/WebAssembly/tool-conventions/pull/170
binaryen change: https://github.com/WebAssembly/binaryen/pull/4141
wabt change:  https://github.com/WebAssembly/wabt/pull/1707
emscripten change: https://github.com/emscripten-core/emscripten/pull/15019

Differential Revision: https://reviews.llvm.org/D109595
2021-09-12 05:30:38 -07:00
Sam Clegg
c468dc1b12 [lld][WebAssembly] Handle weakly defined symbols in shared libraries.
In the case of weakly defined symbols in shared libraries we now
generate both an import and an export.  The dynamic linker can then
choose how a winner from among all the shared libraries that define a
given symbol.

Previously any direct usage of a weakly defined symbol would use the
DSO-local definition (For example, even through there would be single
address for a weakly defined function, each DSO could end up directly
calling its local version).

Fixes: https://github.com/emscripten-core/emscripten/issues/13773

Differential Revision: https://reviews.llvm.org/D108413
2021-08-19 19:25:49 -04:00
Nick Fitzgerald
1d445a6e76 Reland: "[WebAssembly] Deduplicate imports of the same module name, field name, and type"
When two symbols import the same thing, only one import should be
emitted in the Wasm file.

Fixes https://bugs.llvm.org/show_bug.cgi?id=50938

Reverted in: 16aac493e59519377071e900d119ba2e7e5b525d.

Reviewed By: sbc100

Differential Revision: https://reviews.llvm.org/D105519
2021-07-22 14:16:05 -07:00
Sam Clegg
f428693de0 Reland "[lld][WebAssembly] Cleanup duplicate fields in Symbols.h. NFC"
This avoids duplication and simplifies the code in several places
without increasing the size of the symbol union (at least not
above the assert'd limit of 120 bytes).

Originally commit: 9b965b37c75d626c01951184088314590e38d299
Reverted in: 16aac493e59519377071e900d119ba2e7e5b525d.

Differential Revision: https://reviews.llvm.org/D106026
2021-07-20 12:13:08 -07:00