rustc: Use link_section, not wasm_custom_section

This commit transitions definitions of custom sections on the wasm target from
the unstable `#[wasm_custom_section]` attribute to the
already-stable-for-other-targets `#[link_section]` attribute. Mostly the same
restrictions apply as before, except that this now applies only to statics.

Closes #51088
This commit is contained in:
Alex Crichton 2018-07-13 11:30:47 -07:00
parent 50702b2838
commit b7ef674832
26 changed files with 148 additions and 329 deletions

View File

@ -81,10 +81,6 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> {
self.tcx.sess.span_err(attr.span, "\
must only be attached to foreign modules");
}
} else if attr.check_name("wasm_custom_section") {
if target != Target::Const {
self.tcx.sess.span_err(attr.span, "only allowed on consts");
}
}
}

View File

@ -2266,20 +2266,22 @@ pub struct CodegenFnAttrs {
pub export_name: Option<Symbol>,
pub target_features: Vec<Symbol>,
pub linkage: Option<Linkage>,
pub wasm_custom_section: Option<Symbol>,
pub link_section: Option<Symbol>,
}
bitflags! {
#[derive(RustcEncodable, RustcDecodable)]
pub struct CodegenFnAttrFlags: u8 {
const COLD = 0b0000_0001;
const ALLOCATOR = 0b0000_0010;
const UNWIND = 0b0000_0100;
const RUSTC_ALLOCATOR_NOUNWIND = 0b0000_1000;
const NAKED = 0b0001_0000;
const NO_MANGLE = 0b0010_0000;
const RUSTC_STD_INTERNAL_SYMBOL = 0b0100_0000;
const NO_DEBUG = 0b1000_0000;
pub struct CodegenFnAttrFlags: u32 {
const COLD = 1 << 0;
const ALLOCATOR = 1 << 1;
const UNWIND = 1 << 2;
const RUSTC_ALLOCATOR_NOUNWIND = 1 << 3;
const NAKED = 1 << 4;
const NO_MANGLE = 1 << 5;
const RUSTC_STD_INTERNAL_SYMBOL = 1 << 6;
const NO_DEBUG = 1 << 7;
const THREAD_LOCAL = 1 << 8;
const USED = 1 << 9;
}
}
@ -2291,7 +2293,7 @@ impl CodegenFnAttrs {
export_name: None,
target_features: vec![],
linkage: None,
wasm_custom_section: None,
link_section: None,
}
}

View File

@ -1120,7 +1120,7 @@ impl_stable_hash_for!(struct hir::CodegenFnAttrs {
export_name,
target_features,
linkage,
wasm_custom_section,
link_section,
});
impl<'hir> HashStable<StableHashingContext<'hir>> for hir::CodegenFnAttrFlags

View File

@ -313,11 +313,6 @@ fn has_allow_dead_code_or_lang_attr(tcx: TyCtxt,
return true;
}
// These constants are special for wasm
if attr::contains_name(attrs, "wasm_custom_section") {
return true;
}
tcx.lint_level_at_node(lint::builtin::DEAD_CODE, id).0 == lint::Allow
}

View File

@ -24,7 +24,6 @@ pub enum MonoItem<'tcx> {
Fn(Instance<'tcx>),
Static(DefId),
GlobalAsm(NodeId),
CustomSection(DefId),
}
impl<'tcx> MonoItem<'tcx> {
@ -38,8 +37,7 @@ impl<'tcx> MonoItem<'tcx> {
// Conservatively estimate the size of a static declaration
// or assembly to be 1.
MonoItem::Static(_) |
MonoItem::GlobalAsm(_) |
MonoItem::CustomSection(_) => 1,
MonoItem::GlobalAsm(_) => 1,
}
}
}
@ -54,8 +52,7 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for MonoItem<'tcx> {
MonoItem::Fn(ref instance) => {
instance.hash_stable(hcx, hasher);
}
MonoItem::Static(def_id) |
MonoItem::CustomSection(def_id) => {
MonoItem::Static(def_id) => {
def_id.hash_stable(hcx, hasher);
}
MonoItem::GlobalAsm(node_id) => {

View File

@ -33,7 +33,6 @@ use back::link;
use back::write::{self, OngoingCodegen, create_target_machine};
use llvm::{ContextRef, ModuleRef, ValueRef, Vector, get_param};
use llvm;
use libc::c_uint;
use metadata;
use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
use rustc::middle::lang_items::StartFnLangItem;
@ -87,8 +86,7 @@ use std::sync::mpsc;
use syntax_pos::Span;
use syntax_pos::symbol::InternedString;
use syntax::attr;
use rustc::hir;
use syntax::ast;
use rustc::hir::{self, CodegenFnAttrs};
use mir::operand::OperandValue;
@ -513,17 +511,14 @@ pub fn codegen_instance<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, instance: Instance<'
mir::codegen_mir(cx, lldecl, &mir, instance, sig);
}
pub fn set_link_section(cx: &CodegenCx,
llval: ValueRef,
attrs: &[ast::Attribute]) {
if let Some(sect) = attr::first_attr_value_str_by_name(attrs, "link_section") {
if contains_null(&sect.as_str()) {
cx.sess().fatal(&format!("Illegal null byte in link_section value: `{}`", &sect));
}
unsafe {
let buf = CString::new(sect.as_str().as_bytes()).unwrap();
llvm::LLVMSetSection(llval, buf.as_ptr());
}
pub fn set_link_section(llval: ValueRef, attrs: &CodegenFnAttrs) {
let sect = match attrs.link_section {
Some(name) => name,
None => return,
};
unsafe {
let buf = CString::new(sect.as_str().as_bytes()).unwrap();
llvm::LLVMSetSection(llval, buf.as_ptr());
}
}
@ -613,10 +608,6 @@ fn maybe_create_entry_wrapper(cx: &CodegenCx) {
}
}
fn contains_null(s: &str) -> bool {
s.bytes().any(|b| b == 0)
}
fn write_metadata<'a, 'gcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>,
llmod_id: &str,
link_meta: &LinkMeta)
@ -1369,42 +1360,3 @@ mod temp_stable_hash_impls {
}
}
}
pub fn define_custom_section(cx: &CodegenCx, def_id: DefId) {
use rustc::mir::interpret::GlobalId;
assert!(cx.tcx.sess.opts.target_triple.triple().starts_with("wasm32"));
info!("loading wasm section {:?}", def_id);
let section = cx.tcx.codegen_fn_attrs(def_id).wasm_custom_section.unwrap();
let instance = ty::Instance::mono(cx.tcx, def_id);
let cid = GlobalId {
instance,
promoted: None
};
let param_env = ty::ParamEnv::reveal_all();
let val = cx.tcx.const_eval(param_env.and(cid)).unwrap();
let alloc = cx.tcx.const_value_to_allocation(val);
unsafe {
let section = llvm::LLVMMDStringInContext(
cx.llcx,
section.as_str().as_ptr() as *const _,
section.as_str().len() as c_uint,
);
let alloc = llvm::LLVMMDStringInContext(
cx.llcx,
alloc.bytes.as_ptr() as *const _,
alloc.bytes.len() as c_uint,
);
let data = [section, alloc];
let meta = llvm::LLVMMDNodeInContext(cx.llcx, data.as_ptr(), 2);
llvm::LLVMAddNamedMetadataOperand(
cx.llmod,
"wasm.custom_sections\0".as_ptr() as *const _,
meta,
);
}
}

View File

@ -8,6 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use libc::c_uint;
use llvm;
use llvm::{SetUnnamedAddr};
use llvm::{ValueRef, True};
@ -24,11 +25,9 @@ use type_of::LayoutLlvmExt;
use rustc::ty;
use rustc::ty::layout::{Align, LayoutOf};
use rustc::hir;
use rustc::hir::{self, CodegenFnAttrFlags};
use std::ffi::{CStr, CString};
use syntax::ast;
use syntax::attr;
pub fn ptrcast(val: ValueRef, ty: Type) -> ValueRef {
unsafe {
@ -244,11 +243,10 @@ pub fn get_static(cx: &CodegenCx, def_id: DefId) -> ValueRef {
}
pub fn codegen_static<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
def_id: DefId,
is_mutable: bool,
attrs: &[ast::Attribute]) {
def_id: DefId,
is_mutable: bool) {
unsafe {
let g = get_static(cx, def_id);
let attrs = cx.tcx.codegen_fn_attrs(def_id);
let (v, alloc) = match ::mir::codegen_static_initializer(cx, def_id) {
Ok(v) => v,
@ -256,6 +254,8 @@ pub fn codegen_static<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
Err(_) => return,
};
let g = get_static(cx, def_id);
// boolean SSA values are i1, but they have to be stored in i8 slots,
// otherwise some LLVM optimization passes don't work as expected
let mut val_llty = val_ty(v);
@ -307,7 +307,7 @@ pub fn codegen_static<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
debuginfo::create_global_var_metadata(cx, def_id, g);
if attr::contains_name(attrs, "thread_local") {
if attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL) {
llvm::set_thread_local_mode(g, cx.tls_model);
// Do not allow LLVM to change the alignment of a TLS on macOS.
@ -349,9 +349,34 @@ pub fn codegen_static<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
}
}
base::set_link_section(cx, g, attrs);
if attr::contains_name(attrs, "used") {
// Wasm statics with custom link sections get special treatment as they
// go into custom sections of the wasm executable.
if cx.tcx.sess.opts.target_triple.triple().starts_with("wasm32") {
if let Some(section) = attrs.link_section {
let section = llvm::LLVMMDStringInContext(
cx.llcx,
section.as_str().as_ptr() as *const _,
section.as_str().len() as c_uint,
);
let alloc = llvm::LLVMMDStringInContext(
cx.llcx,
alloc.bytes.as_ptr() as *const _,
alloc.bytes.len() as c_uint,
);
let data = [section, alloc];
let meta = llvm::LLVMMDNodeInContext(cx.llcx, data.as_ptr(), 2);
llvm::LLVMAddNamedMetadataOperand(
cx.llmod,
"wasm.custom_sections\0".as_ptr() as *const _,
meta,
);
}
} else {
base::set_link_section(g, &attrs);
}
if attrs.flags.contains(CodegenFnAttrFlags::USED) {
// This static will be stored in the llvm.used variable which is an array of i8*
let cast = llvm::LLVMConstPointerCast(g, Type::i8p(cx).to_ref());
cx.used_statics.borrow_mut().push(cast);

View File

@ -54,9 +54,7 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug + BaseMonoItemExt<'a, 'tcx> {
bug!("Expected Def::Static for {:?}, found nothing", def_id)
}
};
let attrs = tcx.get_attrs(def_id);
consts::codegen_static(&cx, def_id, is_mutable, &attrs);
consts::codegen_static(&cx, def_id, is_mutable);
}
MonoItem::GlobalAsm(node_id) => {
let item = cx.tcx.hir.expect_item(node_id);
@ -66,9 +64,6 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug + BaseMonoItemExt<'a, 'tcx> {
span_bug!(item.span, "Mismatch between hir::Item type and MonoItem type")
}
}
MonoItem::CustomSection(def_id) => {
base::define_custom_section(cx, def_id);
}
MonoItem::Fn(instance) => {
base::codegen_instance(&cx, instance);
}
@ -100,7 +95,6 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug + BaseMonoItemExt<'a, 'tcx> {
MonoItem::Fn(instance) => {
predefine_fn(cx, instance, linkage, visibility, &symbol_name);
}
MonoItem::CustomSection(..) => {}
MonoItem::GlobalAsm(..) => {}
}
@ -120,9 +114,6 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug + BaseMonoItemExt<'a, 'tcx> {
MonoItem::Static(id) => {
format!("Static({:?})", id)
}
MonoItem::CustomSection(id) => {
format!("CustomSection({:?})", id)
}
MonoItem::GlobalAsm(id) => {
format!("GlobalAsm({:?})", id)
}
@ -164,10 +155,10 @@ fn predefine_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
!instance.substs.has_param_types());
let mono_ty = instance.ty(cx.tcx);
let attrs = instance.def.attrs(cx.tcx);
let attrs = cx.tcx.codegen_fn_attrs(instance.def_id());
let lldecl = declare::declare_fn(cx, symbol_name, mono_ty);
unsafe { llvm::LLVMRustSetLinkage(lldecl, base::linkage_to_llvm(linkage)) };
base::set_link_section(cx, lldecl, &attrs);
base::set_link_section(lldecl, &attrs);
if linkage == Linkage::LinkOnceODR ||
linkage == Linkage::WeakODR {
llvm::SetUniqueComdat(cx.llmod, lldecl);

View File

@ -414,9 +414,6 @@ fn collect_items_rec<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
MonoItem::GlobalAsm(..) => {
recursion_depth_reset = None;
}
MonoItem::CustomSection(..) => {
recursion_depth_reset = None;
}
}
record_accesses(tcx, starting_point, &neighbors[..], inlining_map);
@ -993,13 +990,6 @@ impl<'b, 'a, 'v> ItemLikeVisitor<'v> for RootCollector<'b, 'a, 'v> {
hir::ItemKind::Const(..) => {
// const items only generate mono items if they are
// actually used somewhere. Just declaring them is insufficient.
let def_id = self.tcx.hir.local_def_id(item.id);
if self.tcx.sess.opts.target_triple.triple().starts_with("wasm32") &&
self.tcx.codegen_fn_attrs(def_id).wasm_custom_section.is_some()
{
self.output.push(MonoItem::CustomSection(def_id));
}
}
hir::ItemKind::Fn(..) => {
let def_id = self.tcx.hir.local_def_id(item.id);

View File

@ -63,7 +63,6 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug {
instance.substs.types().next().is_some()
}
MonoItem::Static(..) |
MonoItem::CustomSection(..) |
MonoItem::GlobalAsm(..) => false,
}
}
@ -74,9 +73,6 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug {
MonoItem::Static(def_id) => {
tcx.symbol_name(Instance::mono(tcx, def_id))
}
MonoItem::CustomSection(def_id) => {
tcx.symbol_name(Instance::mono(tcx, def_id))
}
MonoItem::GlobalAsm(node_id) => {
let def_id = tcx.hir.local_def_id(node_id);
ty::SymbolName {
@ -126,7 +122,6 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug {
}
}
MonoItem::Static(..) |
MonoItem::CustomSection(..) |
MonoItem::GlobalAsm(..) => {
InstantiationMode::GloballyShared { may_conflict: false }
}
@ -137,7 +132,6 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug {
let def_id = match *self.as_mono_item() {
MonoItem::Fn(ref instance) => instance.def_id(),
MonoItem::Static(def_id) => def_id,
MonoItem::CustomSection(..) => return None,
MonoItem::GlobalAsm(..) => return None,
};
@ -175,7 +169,6 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug {
let (def_id, substs) = match *self.as_mono_item() {
MonoItem::Fn(ref instance) => (instance.def_id(), instance.substs),
MonoItem::Static(def_id) => (def_id, Substs::empty()),
MonoItem::CustomSection(..) => return true,
// global asm never has predicates
MonoItem::GlobalAsm(..) => return true
};
@ -192,10 +185,6 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug {
let instance = Instance::new(def_id, tcx.intern_substs(&[]));
to_string_internal(tcx, "static ", instance)
},
MonoItem::CustomSection(def_id) => {
let instance = Instance::new(def_id, tcx.intern_substs(&[]));
to_string_internal(tcx, "custom-section ", instance)
},
MonoItem::GlobalAsm(..) => {
"global_asm".to_string()
}
@ -221,9 +210,6 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug {
MonoItem::Static(def_id) => {
tcx.hir.as_local_node_id(def_id)
}
MonoItem::CustomSection(def_id) => {
tcx.hir.as_local_node_id(def_id)
}
MonoItem::GlobalAsm(node_id) => {
Some(node_id)
}

View File

@ -180,8 +180,7 @@ pub trait CodegenUnitExt<'tcx> {
}
}
}
MonoItem::Static(def_id) |
MonoItem::CustomSection(def_id) => {
MonoItem::Static(def_id) => {
tcx.hir.as_local_node_id(def_id)
}
MonoItem::GlobalAsm(node_id) => {
@ -450,9 +449,6 @@ fn place_root_mono_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
};
(Linkage::External, visibility)
}
MonoItem::CustomSection(..) => {
(Linkage::External, Visibility::Hidden)
}
MonoItem::GlobalAsm(node_id) => {
let def_id = tcx.hir.local_def_id(node_id);
let visibility = if tcx.is_reachable_non_generic(def_id) {
@ -718,7 +714,6 @@ fn characteristic_def_id_of_mono_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
Some(def_id)
}
MonoItem::Static(def_id) => Some(def_id),
MonoItem::CustomSection(def_id) => Some(def_id),
MonoItem::GlobalAsm(node_id) => Some(tcx.hir.local_def_id(node_id)),
}
}

View File

@ -1270,14 +1270,12 @@ pub fn check_item_type<'a,'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, it: &'tcx hir::Item
match it.node {
// Consts can play a role in type-checking, so they are included here.
hir::ItemKind::Static(..) => {
tcx.typeck_tables_of(tcx.hir.local_def_id(it.id));
let def_id = tcx.hir.local_def_id(it.id);
tcx.typeck_tables_of(def_id);
maybe_check_static_with_link_section(tcx, def_id, it.span);
}
hir::ItemKind::Const(..) => {
tcx.typeck_tables_of(tcx.hir.local_def_id(it.id));
if it.attrs.iter().any(|a| a.check_name("wasm_custom_section")) {
let def_id = tcx.hir.local_def_id(it.id);
check_const_is_u8_array(tcx, def_id, it.span);
}
}
hir::ItemKind::Enum(ref enum_definition, _) => {
check_enum(tcx,
@ -1350,19 +1348,38 @@ pub fn check_item_type<'a,'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, it: &'tcx hir::Item
}
}
fn check_const_is_u8_array<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
def_id: DefId,
span: Span) {
match tcx.type_of(def_id).sty {
ty::TyArray(t, _) => {
match t.sty {
ty::TyUint(ast::UintTy::U8) => return,
_ => {}
}
}
_ => {}
fn maybe_check_static_with_link_section(tcx: TyCtxt, id: DefId, span: Span) {
// Only restricted on wasm32 target for now
if !tcx.sess.opts.target_triple.triple().starts_with("wasm32") {
return
}
// If `#[link_section]` is missing, then nothing to verify
let attrs = tcx.codegen_fn_attrs(id);
if attrs.link_section.is_none() {
return
}
// For the wasm32 target statics with #[link_section] are placed into custom
// sections of the final output file, but this isn't link custom sections of
// other executable formats. Namely we can only embed a list of bytes,
// nothing with pointers to anything else or relocations. If any relocation
// show up, reject them here.
let instance = ty::Instance::mono(tcx, id);
let cid = GlobalId {
instance,
promoted: None
};
let param_env = ty::ParamEnv::reveal_all();
if let Ok(static_) = tcx.const_eval(param_env.and(cid)) {
let alloc = tcx.const_value_to_allocation(static_);
if alloc.relocations.len() != 0 {
let msg = "statics with a custom `#[link_section]` must be a \
simple list of bytes on the wasm target with no \
extra levels of indirection such as references";
tcx.sess.span_err(span, msg);
}
}
tcx.sess.span_err(span, "must be an array of bytes like `[u8; N]`");
}
fn check_on_unimplemented<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,

View File

@ -1867,6 +1867,10 @@ fn codegen_fn_attrs<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefId) -> Codegen
codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL;
} else if attr.check_name("no_debug") {
codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_DEBUG;
} else if attr.check_name("used") {
codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED;
} else if attr.check_name("thread_local") {
codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL;
} else if attr.check_name("inline") {
codegen_fn_attrs.inline = attrs.iter().fold(InlineAttr::None, |ia, attr| {
if attr.path != "inline" {
@ -1929,12 +1933,14 @@ fn codegen_fn_attrs<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefId) -> Codegen
if let Some(val) = attr.value_str() {
codegen_fn_attrs.linkage = Some(linkage_by_name(tcx, id, &val.as_str()));
}
} else if attr.check_name("wasm_custom_section") {
match attr.value_str() {
Some(name) => codegen_fn_attrs.wasm_custom_section = Some(name),
None => {
tcx.sess.span_err(attr.span, "must be of the form \
#[wasm_custom_section = \"foo\"]");
} else if attr.check_name("link_section") {
if let Some(val) = attr.value_str() {
if val.as_str().bytes().any(|b| b == 0) {
let msg = format!("illegal null byte in link_section \
value: `{}`", &val);
tcx.sess.span_err(attr.span, &msg);
} else {
codegen_fn_attrs.link_section = Some(val);
}
}
}

View File

@ -417,9 +417,6 @@ declare_features! (
// `use path as _;` and `extern crate c as _;`
(active, underscore_imports, "1.26.0", Some(48216), None),
// The #[wasm_custom_section] attribute
(active, wasm_custom_section, "1.26.0", Some(51088), None),
// The #![wasm_import_module] attribute
(active, wasm_import_module, "1.26.0", Some(52090), None),
@ -1077,11 +1074,6 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG
"infer outlives requirements is an experimental feature",
cfg_fn!(infer_outlives_requirements))),
("wasm_custom_section", Whitelisted, Gated(Stability::Unstable,
"wasm_custom_section",
"attribute is currently unstable",
cfg_fn!(wasm_custom_section))),
// RFC 2070
("panic_implementation", Normal, Gated(Stability::Unstable,
"panic_implementation",

View File

@ -15,7 +15,7 @@
#![feature(rustc_attrs)]
#![crate_type = "rlib"]
#![rustc_partition_codegened(module="issue_49595-tests", cfg="cfail2")]
#![rustc_partition_codegened(module="issue_49595-__test", cfg="cfail2")]
#![rustc_partition_codegened(module="issue_49595-lit_test", cfg="cfail3")]
mod tests {

View File

@ -14,11 +14,11 @@
extern crate foo;
#[wasm_custom_section = "foo"]
const A: [u8; 2] = [5, 6];
#[link_section = "foo"]
pub static A: [u8; 2] = [5, 6];
#[wasm_custom_section = "baz"]
const B: [u8; 2] = [7, 8];
#[link_section = "baz"]
pub static B: [u8; 2] = [7, 8];
#[no_mangle]
pub extern fn foo() {}

View File

@ -12,8 +12,8 @@
#![feature(wasm_custom_section)]
#![deny(warnings)]
#[wasm_custom_section = "foo"]
const A: [u8; 2] = [1, 2];
#[link_section = "foo"]
pub static A: [u8; 2] = [1, 2];
#[wasm_custom_section = "bar"]
const B: [u8; 2] = [3, 4];
#[link_section = "bar"]
pub static B: [u8; 2] = [3, 4];

View File

@ -1,14 +0,0 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[wasm_custom_section = "foo"] //~ ERROR: attribute is currently unstable
const A: [u8; 2] = [1, 2];
fn main() {}

View File

@ -1,11 +0,0 @@
error[E0658]: attribute is currently unstable (see issue #51088)
--> $DIR/feature-gate-wasm_custom_section.rs:11:1
|
LL | #[wasm_custom_section = "foo"] //~ ERROR: attribute is currently unstable
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: add #![feature(wasm_custom_section)] to the crate attributes to enable
error: aborting due to previous error
For more information about this error, try `rustc --explain E0658`.

View File

@ -8,12 +8,16 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(wasm_custom_section)]
// only-wasm32
#[wasm_custom_section] //~ ERROR: must be of the form
const A: [u8; 1] = [0];
#[link_section = "test"]
pub static A: &[u8] = &[1]; //~ ERROR: no extra levels of indirection
#[wasm_custom_section(foo)] //~ ERROR: must be of the form
const B: [u8; 1] = [0];
#[link_section = "test"]
pub static B: [u8; 3] = [1, 2, 3];
fn main() {}
#[link_section = "test"]
pub static C: usize = 3;
#[link_section = "test"]
pub static D: &usize = &C; //~ ERROR: no extra levels of indirection

View File

@ -0,0 +1,19 @@
error[E0601]: `main` function not found in crate `wasm_custom_section_relocations`
|
= note: consider adding a `main` function to `$DIR/wasm-custom-section-relocations.rs`
error: statics with a custom `#[link_section]` must be a simple list of bytes on the wasm target with no extra levels of indirection such as references
--> $DIR/wasm-custom-section-relocations.rs:14:1
|
LL | pub static A: &[u8] = &[1]; //~ ERROR: no extra levels of indirection
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: statics with a custom `#[link_section]` must be a simple list of bytes on the wasm target with no extra levels of indirection such as references
--> $DIR/wasm-custom-section-relocations.rs:23:1
|
LL | pub static D: &usize = &C; //~ ERROR: no extra levels of indirection
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0601`.

View File

@ -1,14 +0,0 @@
error: must be of the form #[wasm_custom_section = "foo"]
--> $DIR/malformed.rs:13:1
|
LL | #[wasm_custom_section] //~ ERROR: must be of the form
| ^^^^^^^^^^^^^^^^^^^^^^
error: must be of the form #[wasm_custom_section = "foo"]
--> $DIR/malformed.rs:16:1
|
LL | #[wasm_custom_section(foo)] //~ ERROR: must be of the form
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 2 previous errors

View File

@ -1,29 +0,0 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(wasm_custom_section)]
#[wasm_custom_section = "foo"] //~ ERROR: only allowed on consts
static A: [u8; 2] = [1, 2];
#[wasm_custom_section = "foo"] //~ ERROR: only allowed on consts
struct B {}
#[wasm_custom_section = "foo"] //~ ERROR: only allowed on consts
enum C {}
#[wasm_custom_section = "foo"] //~ ERROR: only allowed on consts
impl B {}
#[wasm_custom_section = "foo"] //~ ERROR: only allowed on consts
mod d {}
#[wasm_custom_section = "foo"] //~ ERROR: only allowed on consts
fn main() {}

View File

@ -1,38 +0,0 @@
error: only allowed on consts
--> $DIR/not-const.rs:13:1
|
LL | #[wasm_custom_section = "foo"] //~ ERROR: only allowed on consts
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: only allowed on consts
--> $DIR/not-const.rs:16:1
|
LL | #[wasm_custom_section = "foo"] //~ ERROR: only allowed on consts
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: only allowed on consts
--> $DIR/not-const.rs:19:1
|
LL | #[wasm_custom_section = "foo"] //~ ERROR: only allowed on consts
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: only allowed on consts
--> $DIR/not-const.rs:22:1
|
LL | #[wasm_custom_section = "foo"] //~ ERROR: only allowed on consts
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: only allowed on consts
--> $DIR/not-const.rs:25:1
|
LL | #[wasm_custom_section = "foo"] //~ ERROR: only allowed on consts
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: only allowed on consts
--> $DIR/not-const.rs:28:1
|
LL | #[wasm_custom_section = "foo"] //~ ERROR: only allowed on consts
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 6 previous errors

View File

@ -1,22 +0,0 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(wasm_custom_section)]
#[wasm_custom_section = "foo"]
const A: u8 = 0; //~ ERROR: must be an array of bytes
#[wasm_custom_section = "foo"]
const B: &[u8] = &[0]; //~ ERROR: must be an array of bytes
#[wasm_custom_section = "foo"]
const C: &[u8; 1] = &[0]; //~ ERROR: must be an array of bytes
fn main() {}

View File

@ -1,20 +0,0 @@
error: must be an array of bytes like `[u8; N]`
--> $DIR/not-slice.rs:14:1
|
LL | const A: u8 = 0; //~ ERROR: must be an array of bytes
| ^^^^^^^^^^^^^^^^
error: must be an array of bytes like `[u8; N]`
--> $DIR/not-slice.rs:17:1
|
LL | const B: &[u8] = &[0]; //~ ERROR: must be an array of bytes
| ^^^^^^^^^^^^^^^^^^^^^^
error: must be an array of bytes like `[u8; N]`
--> $DIR/not-slice.rs:20:1
|
LL | const C: &[u8; 1] = &[0]; //~ ERROR: must be an array of bytes
| ^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 3 previous errors