Rollup merge of #121533 - ratmice:wasm_init_fini_array, r=nnethercote

Handle .init_array link_section specially on wasm

Given that wasm-ld now has support for [.init_array](8f2bd8ae68/llvm/lib/MC/WasmObjectWriter.cpp (L1852)), it appears we can easily implement that section by falling through to the normal path rather than taking the typical custom_section path for wasm.

The wasm-ld appears to have a bunch of limitations. Only one static with the `link_section` in a crate or else you hit the fatal error in the link above "only one .init_array section fragment supported". They do not get merged.

You can still call multiple constructors by setting it to an array.

```
unsafe extern "C" fn ctor() {
    println!("foo");
}
#[used]
#[link_section = ".init_array"]
static FOO: [unsafe extern "C" fn(); 2] = [ctor, ctor];
```

Another issue appears to be that if crate *A* depends on crate *B*, but *A* doesn't call any symbols from *B* and *B* doesn't `#[export_name = ...]` any symbols, then crate *B*'s constructor will not be called.  The workaround to this is to provide an exported symbol in crate *B*.
This commit is contained in:
Trevor Gross 2024-07-19 03:27:46 -05:00 committed by GitHub
commit 986d6bf9fb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 36 additions and 9 deletions

View file

@ -495,8 +495,14 @@ impl<'ll> CodegenCx<'ll, '_> {
}
// Wasm statics with custom link sections get special treatment as they
// go into custom sections of the wasm executable.
if self.tcx.sess.target.is_like_wasm {
// go into custom sections of the wasm executable. The exception to this
// is the `.init_array` section which are treated specially by the wasm linker.
if self.tcx.sess.target.is_like_wasm
&& attrs
.link_section
.map(|link_section| !link_section.as_str().starts_with(".init_array"))
.unwrap_or(true)
{
if let Some(section) = attrs.link_section {
let section = llvm::LLVMMDStringInContext2(
self.llcx,