Handle .init_array link_section specially on wasm

This commit is contained in:
matt rice 2024-02-23 16:05:28 -08:00
parent 2dbd6233cc
commit a85700a1a8
2 changed files with 21 additions and 9 deletions

View File

@ -481,8 +481,14 @@ impl<'ll> StaticMethods for CodegenCx<'ll, '_> {
} }
// Wasm statics with custom link sections get special treatment as they // Wasm statics with custom link sections get special treatment as they
// go into custom sections of the wasm executable. // go into custom sections of the wasm executable. The exception to this
if self.tcx.sess.target.is_like_wasm { // 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 { if let Some(section) = attrs.link_section {
let section = llvm::LLVMMDStringInContext2( let section = llvm::LLVMMDStringInContext2(
self.llcx, self.llcx,

View File

@ -159,21 +159,27 @@ fn maybe_check_static_with_link_section(tcx: TyCtxt<'_>, id: LocalDefId) {
return; return;
} }
// For the wasm32 target statics with `#[link_section]` are placed into custom // For the wasm32 target statics with `#[link_section]` other than `.init_array`
// sections of the final output file, but this isn't link custom sections of // are placed into custom sections of the final output file, but this isn't link
// other executable formats. Namely we can only embed a list of bytes, // custom sections of other executable formats. Namely we can only embed a list
// nothing with provenance (pointers to anything else). If any provenance // of bytes, nothing with provenance (pointers to anything else). If any
// show up, reject it here. // provenance show up, reject it here.
// `#[link_section]` may contain arbitrary, or even undefined bytes, but it is // `#[link_section]` may contain arbitrary, or even undefined bytes, but it is
// the consumer's responsibility to ensure all bytes that have been read // the consumer's responsibility to ensure all bytes that have been read
// have defined values. // have defined values.
if let Ok(alloc) = tcx.eval_static_initializer(id.to_def_id()) if let Ok(alloc) = tcx.eval_static_initializer(id.to_def_id())
&& alloc.inner().provenance().ptrs().len() != 0 && alloc.inner().provenance().ptrs().len() != 0
{ {
let msg = "statics with a custom `#[link_section]` must be a \ if attrs
.link_section
.map(|link_section| !link_section.as_str().starts_with(".init_array"))
.unwrap_or(true)
{
let msg = "statics with a custom `#[link_section]` must be a \
simple list of bytes on the wasm target with no \ simple list of bytes on the wasm target with no \
extra levels of indirection such as references"; extra levels of indirection such as references";
tcx.dcx().span_err(tcx.def_span(id), msg); tcx.dcx().span_err(tcx.def_span(id), msg);
}
} }
} }