Skip to content

Commit f836ae4

Browse files
committed
Rollup merge of rust-lang#48883 - alexcrichton:wasm-custom-sections, r=nikomatsakis
rustc: Add a `#[wasm_custom_section]` attribute This commit is an implementation of adding custom sections to wasm artifacts in rustc. The intention here is to expose the ability of the wasm binary format to contain custom sections with arbitrary user-defined data. Currently neither our version of LLVM nor LLD supports this so the implementation is currently custom to rustc itself. The implementation here is to attach a `#[wasm_custom_section = "foo"]` attribute to any `const` which has a type like `[u8; N]`. Other types of constants aren't supported yet but may be added one day! This should hopefully be enough to get off the ground with *some* custom section support. The current semantics are that any constant tagged with `#[wasm_custom_section]` section will be *appended* to the corresponding section in the final output wasm artifact (and this affects dependencies linked in as well, not just the final crate). This means that whatever is interpreting the contents must be able to interpret binary-concatenated sections (or each constant needs to be in its own custom section). To test this change the existing `run-make` test suite was moved to a `run-make-fulldeps` folder and a new `run-make` test suite was added which applies to all targets by default. This test suite currently only has one test which only runs for the wasm target (using a node.js script to use `WebAssembly` in JS to parse the wasm output).
2 parents 16eeb10 + d889957 commit f836ae4

File tree

591 files changed

+1145
-62
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

591 files changed

+1145
-62
lines changed

src/bootstrap/builder.rs

+1
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,7 @@ impl<'a> Builder<'a> {
313313
test::RunPassFullDepsPretty, test::RunFailFullDepsPretty,
314314
test::Crate, test::CrateLibrustc, test::CrateRustdoc, test::Linkcheck,
315315
test::Cargotest, test::Cargo, test::Rls, test::ErrorIndex, test::Distcheck,
316+
test::RunMakeFullDeps,
316317
test::Nomicon, test::Reference, test::RustdocBook, test::RustByExample,
317318
test::TheBook, test::UnstableBook,
318319
test::Rustfmt, test::Miri, test::Clippy, test::RustdocJS, test::RustdocTheme,

src/bootstrap/compile.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -915,7 +915,7 @@ impl Step for Assemble {
915915
}
916916
}
917917

918-
let lld_install = if build.config.lld_enabled && target_compiler.stage > 0 {
918+
let lld_install = if build.config.lld_enabled {
919919
Some(builder.ensure(native::Lld {
920920
target: target_compiler.host,
921921
}))

src/bootstrap/test.rs

+12-7
Original file line numberDiff line numberDiff line change
@@ -759,12 +759,18 @@ test!(RunFailFullDepsPretty {
759759
host: true
760760
});
761761

762-
host_test!(RunMake {
762+
default_test!(RunMake {
763763
path: "src/test/run-make",
764764
mode: "run-make",
765765
suite: "run-make"
766766
});
767767

768+
host_test!(RunMakeFullDeps {
769+
path: "src/test/run-make-fulldeps",
770+
mode: "run-make",
771+
suite: "run-make-fulldeps"
772+
});
773+
768774
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
769775
struct Compiletest {
770776
compiler: Compiler,
@@ -827,8 +833,7 @@ impl Step for Compiletest {
827833
// FIXME: Does pretty need librustc compiled? Note that there are
828834
// fulldeps test suites with mode = pretty as well.
829835
mode == "pretty" ||
830-
mode == "rustdoc" ||
831-
mode == "run-make" {
836+
mode == "rustdoc" {
832837
builder.ensure(compile::Rustc { compiler, target });
833838
}
834839

@@ -849,7 +854,7 @@ impl Step for Compiletest {
849854
cmd.arg("--rustc-path").arg(builder.rustc(compiler));
850855

851856
// Avoid depending on rustdoc when we don't need it.
852-
if mode == "rustdoc" || mode == "run-make" {
857+
if mode == "rustdoc" || (mode == "run-make" && suite.ends_with("fulldeps")) {
853858
cmd.arg("--rustdoc-path").arg(builder.rustdoc(compiler.host));
854859
}
855860

@@ -931,7 +936,7 @@ impl Step for Compiletest {
931936

932937
// Only pass correct values for these flags for the `run-make` suite as it
933938
// requires that a C++ compiler was configured which isn't always the case.
934-
if suite == "run-make" {
939+
if suite == "run-make-fulldeps" {
935940
let llvm_components = output(Command::new(&llvm_config).arg("--components"));
936941
let llvm_cxxflags = output(Command::new(&llvm_config).arg("--cxxflags"));
937942
cmd.arg("--cc").arg(build.cc(target))
@@ -944,12 +949,12 @@ impl Step for Compiletest {
944949
}
945950
}
946951
}
947-
if suite == "run-make" && !build.config.llvm_enabled {
952+
if suite == "run-make-fulldeps" && !build.config.llvm_enabled {
948953
println!("Ignoring run-make test suite as they generally don't work without LLVM");
949954
return;
950955
}
951956

952-
if suite != "run-make" {
957+
if suite != "run-make-fulldeps" {
953958
cmd.arg("--cc").arg("")
954959
.arg("--cxx").arg("")
955960
.arg("--cflags").arg("")

src/ci/docker/wasm32-unknown/Dockerfile

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ ENV RUST_CONFIGURE_ARGS \
2626
--set rust.lld
2727

2828
ENV SCRIPT python2.7 /checkout/x.py test --target $TARGETS \
29+
src/test/run-make \
2930
src/test/ui \
3031
src/test/run-pass \
3132
src/test/compile-fail \

src/librustc/dep_graph/dep_node.rs

+5
Original file line numberDiff line numberDiff line change
@@ -593,6 +593,7 @@ define_dep_nodes!( <'tcx>
593593
[] ImplementationsOfTrait { krate: CrateNum, trait_id: DefId },
594594
[] AllTraitImplementations(CrateNum),
595595

596+
[] DllimportForeignItems(CrateNum),
596597
[] IsDllimportForeignItem(DefId),
597598
[] IsStaticallyIncludedForeignItem(DefId),
598599
[] NativeLibraryKind(DefId),
@@ -650,9 +651,13 @@ define_dep_nodes!( <'tcx>
650651

651652
[] GetSymbolExportLevel(DefId),
652653

654+
[] WasmCustomSections(CrateNum),
655+
653656
[input] Features,
654657

655658
[] ProgramClausesFor(DefId),
659+
[] WasmImportModuleMap(CrateNum),
660+
[] ForeignModules(CrateNum),
656661
);
657662

658663
trait DepNodeParams<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> : fmt::Debug {

src/librustc/hir/check_attr.rs

+35-3
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ enum Target {
2525
Struct,
2626
Union,
2727
Enum,
28+
Const,
29+
ForeignMod,
2830
Other,
2931
}
3032

@@ -35,6 +37,8 @@ impl Target {
3537
hir::ItemStruct(..) => Target::Struct,
3638
hir::ItemUnion(..) => Target::Union,
3739
hir::ItemEnum(..) => Target::Enum,
40+
hir::ItemConst(..) => Target::Const,
41+
hir::ItemForeignMod(..) => Target::ForeignMod,
3842
_ => Target::Other,
3943
}
4044
}
@@ -55,14 +59,42 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> {
5559
.emit();
5660
}
5761

62+
let mut has_wasm_import_module = false;
5863
for attr in &item.attrs {
59-
if let Some(name) = attr.name() {
60-
if name == "inline" {
61-
self.check_inline(attr, item, target)
64+
if attr.check_name("inline") {
65+
self.check_inline(attr, item, target)
66+
} else if attr.check_name("wasm_import_module") {
67+
has_wasm_import_module = true;
68+
if attr.value_str().is_none() {
69+
self.tcx.sess.span_err(attr.span, "\
70+
must be of the form #[wasm_import_module = \"...\"]");
71+
}
72+
if target != Target::ForeignMod {
73+
self.tcx.sess.span_err(attr.span, "\
74+
must only be attached to foreign modules");
75+
}
76+
} else if attr.check_name("wasm_custom_section") {
77+
if target != Target::Const {
78+
self.tcx.sess.span_err(attr.span, "only allowed on consts");
79+
}
80+
81+
if attr.value_str().is_none() {
82+
self.tcx.sess.span_err(attr.span, "must be of the form \
83+
#[wasm_custom_section = \"foo\"]");
6284
}
6385
}
6486
}
6587

88+
if target == Target::ForeignMod &&
89+
!has_wasm_import_module &&
90+
self.tcx.sess.target.target.arch == "wasm32" &&
91+
false // FIXME: eventually enable this warning when stable
92+
{
93+
self.tcx.sess.span_warn(item.span, "\
94+
must have a #[wasm_import_module = \"...\"] attribute, this \
95+
will become a hard error before too long");
96+
}
97+
6698
self.check_repr(item, target);
6799
}
68100

src/librustc/ich/impls_cstore.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,12 @@ impl_stable_hash_for!(struct middle::cstore::NativeLibrary {
3333
kind,
3434
name,
3535
cfg,
36-
foreign_items
36+
foreign_module
37+
});
38+
39+
impl_stable_hash_for!(struct middle::cstore::ForeignModule {
40+
foreign_items,
41+
def_id
3742
});
3843

3944
impl_stable_hash_for!(enum middle::cstore::LinkagePreference {

src/librustc/middle/cstore.rs

+6
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,13 @@ pub struct NativeLibrary {
132132
pub kind: NativeLibraryKind,
133133
pub name: Symbol,
134134
pub cfg: Option<ast::MetaItem>,
135+
pub foreign_module: Option<DefId>,
136+
}
137+
138+
#[derive(Clone, Hash, RustcEncodable, RustcDecodable)]
139+
pub struct ForeignModule {
135140
pub foreign_items: Vec<DefId>,
141+
pub def_id: DefId,
136142
}
137143

138144
pub enum LoadedMacro {

src/librustc/middle/dead.rs

+5
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,11 @@ fn has_allow_dead_code_or_lang_attr(tcx: TyCtxt,
318318
return true;
319319
}
320320

321+
// These constants are special for wasm
322+
if attr::contains_name(attrs, "wasm_custom_section") {
323+
return true;
324+
}
325+
321326
tcx.lint_level_at_node(lint::builtin::DEAD_CODE, id).0 == lint::Allow
322327
}
323328

src/librustc/ty/maps/config.rs

+24
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,12 @@ impl<'tcx> QueryDescription<'tcx> for queries::native_libraries<'tcx> {
430430
}
431431
}
432432

433+
impl<'tcx> QueryDescription<'tcx> for queries::foreign_modules<'tcx> {
434+
fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
435+
format!("looking up the foreign modules of a linked crate")
436+
}
437+
}
438+
433439
impl<'tcx> QueryDescription<'tcx> for queries::plugin_registrar_fn<'tcx> {
434440
fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
435441
format!("looking up the plugin registrar for a crate")
@@ -678,6 +684,12 @@ impl<'tcx> QueryDescription<'tcx> for queries::instance_def_size_estimate<'tcx>
678684
}
679685
}
680686

687+
impl<'tcx> QueryDescription<'tcx> for queries::wasm_custom_sections<'tcx> {
688+
fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
689+
format!("custom wasm sections for a crate")
690+
}
691+
}
692+
681693
impl<'tcx> QueryDescription<'tcx> for queries::generics_of<'tcx> {
682694
#[inline]
683695
fn cache_on_disk(def_id: Self::Key) -> bool {
@@ -699,6 +711,18 @@ impl<'tcx> QueryDescription<'tcx> for queries::program_clauses_for<'tcx> {
699711
}
700712
}
701713

714+
impl<'tcx> QueryDescription<'tcx> for queries::wasm_import_module_map<'tcx> {
715+
fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
716+
format!("wasm import module map")
717+
}
718+
}
719+
720+
impl<'tcx> QueryDescription<'tcx> for queries::dllimport_foreign_items<'tcx> {
721+
fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
722+
format!("wasm import module map")
723+
}
724+
}
725+
702726
macro_rules! impl_disk_cacheable_query(
703727
($query_name:ident, |$key:tt| $cond:expr) => {
704728
impl<'tcx> QueryDescription<'tcx> for queries::$query_name<'tcx> {

src/librustc/ty/maps/mod.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use infer::canonical::{Canonical, QueryResult};
1818
use lint;
1919
use middle::borrowck::BorrowCheckResult;
2020
use middle::cstore::{ExternCrate, LinkagePreference, NativeLibrary,
21-
ExternBodyNestedBodies};
21+
ExternBodyNestedBodies, ForeignModule};
2222
use middle::cstore::{NativeLibraryKind, DepKind, CrateSource, ExternConstBody};
2323
use middle::privacy::AccessLevels;
2424
use middle::reachable::ReachableSet;
@@ -320,6 +320,9 @@ define_maps! { <'tcx>
320320

321321

322322
[] fn native_libraries: NativeLibraries(CrateNum) -> Lrc<Vec<NativeLibrary>>,
323+
324+
[] fn foreign_modules: ForeignModules(CrateNum) -> Lrc<Vec<ForeignModule>>,
325+
323326
[] fn plugin_registrar_fn: PluginRegistrarFn(CrateNum) -> Option<DefId>,
324327
[] fn derive_registrar_fn: DeriveRegistrarFn(CrateNum) -> Option<DefId>,
325328
[] fn crate_disambiguator: CrateDisambiguator(CrateNum) -> CrateDisambiguator,
@@ -331,6 +334,8 @@ define_maps! { <'tcx>
331334
[] fn all_trait_implementations: AllTraitImplementations(CrateNum)
332335
-> Lrc<Vec<DefId>>,
333336

337+
[] fn dllimport_foreign_items: DllimportForeignItems(CrateNum)
338+
-> Lrc<FxHashSet<DefId>>,
334339
[] fn is_dllimport_foreign_item: IsDllimportForeignItem(DefId) -> bool,
335340
[] fn is_statically_included_foreign_item: IsStaticallyIncludedForeignItem(DefId) -> bool,
336341
[] fn native_library_kind: NativeLibraryKind(DefId)
@@ -424,6 +429,10 @@ define_maps! { <'tcx>
424429
[] fn features_query: features_node(CrateNum) -> Lrc<feature_gate::Features>,
425430

426431
[] fn program_clauses_for: ProgramClausesFor(DefId) -> Lrc<Vec<Clause<'tcx>>>,
432+
433+
[] fn wasm_custom_sections: WasmCustomSections(CrateNum) -> Lrc<Vec<DefId>>,
434+
[] fn wasm_import_module_map: WasmImportModuleMap(CrateNum)
435+
-> Lrc<FxHashMap<DefId, String>>,
427436
}
428437

429438
//////////////////////////////////////////////////////////////////////

src/librustc/ty/maps/plumbing.rs

+6
Original file line numberDiff line numberDiff line change
@@ -886,6 +886,9 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
886886
force!(all_trait_implementations, krate!());
887887
}
888888

889+
DepKind::DllimportForeignItems => {
890+
force!(dllimport_foreign_items, krate!());
891+
}
889892
DepKind::IsDllimportForeignItem => {
890893
force!(is_dllimport_foreign_item, def_id!());
891894
}
@@ -940,6 +943,9 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
940943
DepKind::Features => { force!(features_query, LOCAL_CRATE); }
941944

942945
DepKind::ProgramClausesFor => { force!(program_clauses_for, def_id!()); }
946+
DepKind::WasmCustomSections => { force!(wasm_custom_sections, krate!()); }
947+
DepKind::WasmImportModuleMap => { force!(wasm_import_module_map, krate!()); }
948+
DepKind::ForeignModules => { force!(foreign_modules, krate!()); }
943949
}
944950

945951
true

src/librustc_metadata/creader.rs

+1-19
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
1313
use cstore::{self, CStore, CrateSource, MetadataBlob};
1414
use locator::{self, CratePaths};
15-
use native_libs::relevant_lib;
1615
use schema::CrateRoot;
1716
use rustc_data_structures::sync::{Lrc, RwLock, Lock};
1817

@@ -230,7 +229,7 @@ impl<'a> CrateLoader<'a> {
230229
.map(|trait_impls| (trait_impls.trait_id, trait_impls.impls))
231230
.collect();
232231

233-
let mut cmeta = cstore::CrateMetadata {
232+
let cmeta = cstore::CrateMetadata {
234233
name,
235234
extern_crate: Lock::new(None),
236235
def_path_table: Lrc::new(def_path_table),
@@ -250,25 +249,8 @@ impl<'a> CrateLoader<'a> {
250249
rlib,
251250
rmeta,
252251
},
253-
// Initialize this with an empty set. The field is populated below
254-
// after we were able to deserialize its contents.
255-
dllimport_foreign_items: FxHashSet(),
256252
};
257253

258-
let dllimports: FxHashSet<_> = cmeta
259-
.root
260-
.native_libraries
261-
.decode((&cmeta, self.sess))
262-
.filter(|lib| relevant_lib(self.sess, lib) &&
263-
lib.kind == cstore::NativeLibraryKind::NativeUnknown)
264-
.flat_map(|lib| {
265-
assert!(lib.foreign_items.iter().all(|def_id| def_id.krate == cnum));
266-
lib.foreign_items.into_iter().map(|def_id| def_id.index)
267-
})
268-
.collect();
269-
270-
cmeta.dllimport_foreign_items = dllimports;
271-
272254
let cmeta = Lrc::new(cmeta);
273255
self.cstore.set_crate_data(cnum, cmeta.clone());
274256
(cnum, cmeta)

src/librustc_metadata/cstore.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use rustc::middle::cstore::{DepKind, ExternCrate, MetadataLoader};
2020
use rustc::session::{Session, CrateDisambiguator};
2121
use rustc_back::PanicStrategy;
2222
use rustc_data_structures::indexed_vec::IndexVec;
23-
use rustc::util::nodemap::{FxHashMap, FxHashSet, NodeMap};
23+
use rustc::util::nodemap::{FxHashMap, NodeMap};
2424

2525
use rustc_data_structures::sync::{Lrc, RwLock, Lock};
2626
use syntax::{ast, attr};
@@ -30,7 +30,7 @@ use syntax_pos;
3030

3131
pub use rustc::middle::cstore::{NativeLibrary, NativeLibraryKind, LinkagePreference};
3232
pub use rustc::middle::cstore::NativeLibraryKind::*;
33-
pub use rustc::middle::cstore::{CrateSource, LibSource};
33+
pub use rustc::middle::cstore::{CrateSource, LibSource, ForeignModule};
3434

3535
pub use cstore_impl::{provide, provide_extern};
3636

@@ -84,8 +84,6 @@ pub struct CrateMetadata {
8484
pub source: CrateSource,
8585

8686
pub proc_macros: Option<Vec<(ast::Name, Lrc<SyntaxExtension>)>>,
87-
// Foreign items imported from a dylib (Windows only)
88-
pub dllimport_foreign_items: FxHashSet<DefIndex>,
8987
}
9088

9189
pub struct CStore {

0 commit comments

Comments
 (0)