mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-26 16:54:01 +00:00
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:
parent
50702b2838
commit
b7ef674832
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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) => {
|
||||
|
@ -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(§.as_str()) {
|
||||
cx.sess().fatal(&format!("Illegal null byte in link_section value: `{}`", §));
|
||||
}
|
||||
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,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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)),
|
||||
}
|
||||
}
|
||||
|
@ -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>,
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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",
|
||||
|
@ -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 {
|
||||
|
@ -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() {}
|
||||
|
@ -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];
|
||||
|
@ -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() {}
|
@ -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`.
|
@ -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
|
19
src/test/ui/wasm-custom-section-relocations.stderr
Normal file
19
src/test/ui/wasm-custom-section-relocations.stderr
Normal 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`.
|
@ -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
|
||||
|
@ -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() {}
|
@ -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
|
||||
|
@ -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() {}
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user