// Adapted from https://github.com/sunfishcode/mir2cranelift/blob/master/rust-examples/nocore-hello-world.rs
-#![feature(no_core, unboxed_closures, start, lang_items, box_syntax, slice_patterns)]
+#![feature(no_core, unboxed_closures, start, lang_items, box_syntax, slice_patterns, never_type, linkage)]
#![no_core]
#![allow(dead_code)]
}
assert_eq!(((|()| 42u8) as fn(()) -> u8)(()), 42);
+
+ extern {
+ #[linkage = "weak"]
+ static ABC: *const u8;
+ }
+
+ {
+ extern {
+ #[linkage = "weak"]
+ static ABC: *const u8;
+ }
+ }
+
+ unsafe { assert_eq!(ABC as usize, 0); }
}
fx: &mut FunctionCx<'a, 'tcx, impl Backend>,
static_: &Static<'tcx>,
) -> CPlace<'tcx> {
- let data_id = data_id_for_static(fx.tcx, fx.module, static_.def_id, Linkage::Import);
+ let linkage = crate::linkage::get_static_ref_linkage(fx.tcx, static_.def_id);
+ let data_id = data_id_for_static(fx.tcx, fx.module, static_.def_id, linkage);
cplace_for_dataid(fx, static_.ty, data_id)
}
!tcx.type_of(def_id)
.is_freeze(tcx, ParamEnv::reveal_all(), DUMMY_SP)
};
- module
+
+ let data_id = module
.declare_data(&*symbol_name, linkage, is_mutable)
- .unwrap()
+ .unwrap();
+
+ if linkage == Linkage::Preemptible {
+ if let ty::RawPtr(_) = tcx.type_of(def_id).sty {
+ } else {
+ tcx.sess.span_fatal(tcx.def_span(def_id), "must have type `*const T` or `*mut T`")
+ }
+
+ let mut data_ctx = DataContext::new();
+ let zero_bytes = std::iter::repeat(0)
+ .take(pointer_ty(tcx).bytes() as usize)
+ .collect::<Vec<u8>>()
+ .into_boxed_slice();
+ data_ctx.define(zero_bytes);
+ match module.define_data(data_id, &data_ctx) {
+ // Everytime a weak static is referenced, there will be a zero pointer definition,
+ // so duplicate definitions are expected and allowed.
+ Err(ModuleError::DuplicateDefinition(_)) => {}
+ res => res.unwrap(),
+ }
+ }
+
+ data_id
}
fn cplace_for_dataid<'a, 'tcx: 'a>(
}
TodoItem::Static(def_id) => {
//println!("static {:?}", def_id);
+
+ if tcx.is_foreign_item(def_id) {
+ continue;
+ }
+
let instance = ty::Instance::mono(tcx, def_id);
let cid = GlobalId {
instance,
_ => bug!("static const eval returned {:#?}", const_),
};
+ // FIXME set correct linkage
let data_id = data_id_for_static(tcx, module, def_id, Linkage::Export);
(data_id, alloc)
}
}
AllocKind::Static(def_id) => {
cx.todo.insert(TodoItem::Static(def_id));
- data_id_for_static(tcx, module, def_id, Linkage::Import)
+ let linkage = crate::linkage::get_static_ref_linkage(tcx, def_id);
+ data_id_for_static(tcx, module, def_id, linkage)
}
};
use rustc_codegen_ssa::CrateInfo;
use rustc_codegen_utils::codegen_backend::CodegenBackend;
use rustc_codegen_utils::link::out_filename;
+use rustc_mir::monomorphize::partitioning::CodegenUnitExt;
use cranelift::codegen::settings;
use cranelift_faerie::*;
mod intrinsics;
mod link;
mod link_copied;
+mod linkage;
mod main_shim;
mod metadata;
mod pretty_clif;
.downcast::<CodegenResults>()
.expect("Expected CraneliftCodegenBackend's CodegenResult, found Box<Any>");
- for &crate_type in sess.opts.crate_types.iter() {
+ for &crate_type in sess.crate_types.borrow().iter() {
let output_name = out_filename(sess, crate_type, &outputs, &res.crate_name.as_str());
match crate_type {
CrateType::Rlib => link::link_rlib(sess, &res, output_name),
let (_, cgus) = tcx.collect_and_partition_mono_items(LOCAL_CRATE);
let mono_items = cgus
.iter()
- .map(|cgu| cgu.items().iter())
+ .map(|cgu| cgu.items_in_deterministic_order(tcx).into_iter())
.flatten()
- .map(|(&mono_item, &(linkage, vis))| (mono_item, (linkage, vis)))
.collect::<FxHashMap<_, (_, _)>>();
codegen_mono_items(tcx, module, debug.as_mut(), log, mono_items);
) {
let mut cx = CodegenCx::new(tcx, module, debug_context);
time("codegen mono items", move || {
- for (mono_item, (linkage, vis)) in mono_items {
+ for (mono_item, (linkage, visibility)) in mono_items {
unimpl::try_unimpl(tcx, log, || {
- let linkage = match (linkage, vis) {
- (RLinkage::External, Visibility::Default) => Linkage::Export,
- (RLinkage::Internal, Visibility::Default) => Linkage::Local,
- // FIXME this should get external linkage, but hidden visibility,
- // not internal linkage and default visibility
- (RLinkage::External, Visibility::Hidden) => Linkage::Export,
- _ => panic!("{:?} = {:?} {:?}", mono_item, linkage, vis),
- };
+ let linkage = crate::linkage::get_clif_linkage(mono_item, linkage, visibility);
base::trans_mono_item(&mut cx, mono_item, linkage);
});
}
--- /dev/null
+use rustc::mir::mono::{MonoItem, Linkage as RLinkage, Visibility};
+
+use crate::prelude::*;
+
+pub fn get_clif_linkage(mono_item: MonoItem, linkage: RLinkage, visibility: Visibility) -> Linkage {
+ match (linkage, visibility) {
+ (RLinkage::External, Visibility::Default) => Linkage::Export,
+ (RLinkage::Internal, Visibility::Default) => Linkage::Local,
+ // FIXME this should get external linkage, but hidden visibility,
+ // not internal linkage and default visibility
+ (RLinkage::External, Visibility::Hidden) => Linkage::Export,
+ _ => panic!("{:?} = {:?} {:?}", mono_item, linkage, visibility),
+ }
+}
+
+pub fn get_static_ref_linkage(tcx: TyCtxt, def_id: DefId) -> Linkage {
+ let fn_attrs = tcx.codegen_fn_attrs(def_id);
+
+ if let Some(linkage) = fn_attrs.linkage {
+ match linkage {
+ RLinkage::External => Linkage::Export,
+ RLinkage::Internal => Linkage::Local,
+ RLinkage::ExternalWeak | RLinkage::WeakAny => Linkage::Preemptible,
+ _ => panic!("{:?}", linkage),
+ }
+ } else {
+ Linkage::Import
+ }
+}