trans: Make translation of statics collector-driven.
This commit is contained in:
parent
3fa1cdf23c
commit
891c2a082f
|
@ -2249,8 +2249,10 @@ pub fn update_linkage(ccx: &CrateContext,
|
|||
}
|
||||
}
|
||||
|
||||
fn set_global_section(ccx: &CrateContext, llval: ValueRef, i: &hir::Item) {
|
||||
if let Some(sect) = attr::first_attr_value_str_by_name(&i.attrs, "link_section") {
|
||||
pub fn set_link_section(ccx: &CrateContext,
|
||||
llval: ValueRef,
|
||||
attrs: &[ast::Attribute]) {
|
||||
if let Some(sect) = attr::first_attr_value_str_by_name(attrs, "link_section") {
|
||||
if contains_null(§) {
|
||||
ccx.sess().fatal(&format!("Illegal null byte in link_section value: `{}`", §));
|
||||
}
|
||||
|
@ -2280,7 +2282,7 @@ pub fn trans_item(ccx: &CrateContext, item: &hir::Item) {
|
|||
let empty_substs = ccx.empty_substs_for_def_id(def_id);
|
||||
let llfn = Callee::def(ccx, def_id, empty_substs).reify(ccx).val;
|
||||
trans_fn(ccx, &decl, &body, llfn, empty_substs, item.id);
|
||||
set_global_section(ccx, llfn, item);
|
||||
set_link_section(ccx, llfn, &item.attrs);
|
||||
update_linkage(ccx,
|
||||
llfn,
|
||||
Some(item.id),
|
||||
|
@ -2336,13 +2338,9 @@ pub fn trans_item(ccx: &CrateContext, item: &hir::Item) {
|
|||
enum_variant_size_lint(ccx, enum_definition, item.span, item.id);
|
||||
}
|
||||
}
|
||||
hir::ItemStatic(_, m, ref expr) => {
|
||||
let g = match consts::trans_static(ccx, m, expr, item.id, &item.attrs) {
|
||||
Ok(g) => g,
|
||||
Err(err) => ccx.tcx().sess.span_fatal(expr.span, &err.description()),
|
||||
};
|
||||
set_global_section(ccx, g, item);
|
||||
update_linkage(ccx, g, Some(item.id), OriginalTranslation);
|
||||
hir::ItemStatic(..) => {
|
||||
// Don't do anything here. Translation of statics has been moved to
|
||||
// being "collector-driven".
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
@ -2700,6 +2698,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
|
||||
let codegen_units = collect_and_partition_translation_items(&shared_ccx);
|
||||
let codegen_unit_count = codegen_units.len();
|
||||
|
||||
assert!(tcx.sess.opts.cg.codegen_units == codegen_unit_count ||
|
||||
tcx.sess.opts.debugging_opts.incremental.is_some());
|
||||
|
||||
|
@ -2723,6 +2722,33 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
};
|
||||
}
|
||||
|
||||
// Instantiate translation items without filling out definitions yet...
|
||||
for ccx in crate_context_list.iter() {
|
||||
for (&trans_item, &linkage) in &ccx.codegen_unit().items {
|
||||
trans_item.predefine(&ccx, linkage);
|
||||
}
|
||||
}
|
||||
|
||||
// ... and now that we have everything pre-defined, fill out those definitions.
|
||||
for ccx in crate_context_list.iter() {
|
||||
for (&trans_item, _) in &ccx.codegen_unit().items {
|
||||
match trans_item {
|
||||
TransItem::Static(node_id) => {
|
||||
let item = ccx.tcx().map.expect_item(node_id);
|
||||
if let hir::ItemStatic(_, m, ref expr) = item.node {
|
||||
match consts::trans_static(&ccx, m, expr, item.id, &item.attrs) {
|
||||
Ok(_) => { /* Cool, everything's alright. */ },
|
||||
Err(err) => ccx.tcx().sess.span_fatal(expr.span, &err.description()),
|
||||
};
|
||||
} else {
|
||||
span_bug!(item.span, "Mismatch between hir::Item type and TransItem type")
|
||||
}
|
||||
}
|
||||
_ => { }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
let ccx = crate_context_list.get_ccx(0);
|
||||
|
||||
|
|
|
@ -1017,22 +1017,29 @@ pub fn get_static<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, def_id: DefId)
|
|||
|
||||
let g = if let Some(id) = ccx.tcx().map.as_local_node_id(def_id) {
|
||||
let llty = type_of::type_of(ccx, ty);
|
||||
match ccx.tcx().map.get(id) {
|
||||
let (g, attrs) = match ccx.tcx().map.get(id) {
|
||||
hir_map::NodeItem(&hir::Item {
|
||||
span, node: hir::ItemStatic(..), ..
|
||||
ref attrs, span, node: hir::ItemStatic(..), ..
|
||||
}) => {
|
||||
// If this static came from an external crate, then
|
||||
// we need to get the symbol from metadata instead of
|
||||
// using the current crate's name/version
|
||||
// information in the hash of the symbol
|
||||
debug!("making {}", sym);
|
||||
// Make sure that this is never executed for something inlined.
|
||||
assert!(!ccx.external_srcs().borrow().contains_key(&id));
|
||||
|
||||
// Create the global before evaluating the initializer;
|
||||
// this is necessary to allow recursive statics.
|
||||
declare::define_global(ccx, &sym, llty).unwrap_or_else(|| {
|
||||
ccx.sess().span_fatal(span,
|
||||
&format!("symbol `{}` is already defined", sym))
|
||||
})
|
||||
let defined_in_current_codegen_unit = ccx.codegen_unit()
|
||||
.items
|
||||
.contains_key(&TransItem::Static(id));
|
||||
if defined_in_current_codegen_unit {
|
||||
if declare::get_declared_value(ccx, &sym).is_none() {
|
||||
span_bug!(span, "trans: Static not properly pre-defined?");
|
||||
}
|
||||
} else {
|
||||
if declare::get_declared_value(ccx, &sym).is_some() {
|
||||
span_bug!(span, "trans: Conflicting symbol names for static?");
|
||||
}
|
||||
}
|
||||
|
||||
let g = declare::define_global(ccx, &sym, llty).unwrap();
|
||||
|
||||
(g, attrs)
|
||||
}
|
||||
|
||||
hir_map::NodeForeignItem(&hir::ForeignItem {
|
||||
|
@ -1083,17 +1090,19 @@ pub fn get_static<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, def_id: DefId)
|
|||
declare::declare_global(ccx, &sym, llty)
|
||||
};
|
||||
|
||||
for attr in attrs {
|
||||
if attr.check_name("thread_local") {
|
||||
llvm::set_thread_local(g, true);
|
||||
}
|
||||
}
|
||||
|
||||
g
|
||||
(g, attrs)
|
||||
}
|
||||
|
||||
item => bug!("get_static: expected static, found {:?}", item)
|
||||
};
|
||||
|
||||
for attr in attrs {
|
||||
if attr.check_name("thread_local") {
|
||||
llvm::set_thread_local(g, true);
|
||||
}
|
||||
}
|
||||
|
||||
g
|
||||
} else {
|
||||
// FIXME(nagisa): perhaps the map of externs could be offloaded to llvm somehow?
|
||||
// FIXME(nagisa): investigate whether it can be changed into define_global
|
||||
|
@ -1197,6 +1206,9 @@ pub fn trans_static(ccx: &CrateContext,
|
|||
"thread_local") {
|
||||
llvm::set_thread_local(g, true);
|
||||
}
|
||||
|
||||
base::set_link_section(ccx, g, attrs);
|
||||
|
||||
Ok(g)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,9 @@
|
|||
//! item-path. This is used for unit testing the code that generates
|
||||
//! paths etc in all kinds of annoying scenarios.
|
||||
|
||||
use base::llvm_linkage_by_name;
|
||||
use base;
|
||||
use context::CrateContext;
|
||||
use declare;
|
||||
use glue::DropGlueKind;
|
||||
use llvm;
|
||||
use monomorphize::Instance;
|
||||
|
@ -26,6 +28,8 @@ use std::hash::{Hash, Hasher};
|
|||
use syntax::ast::{self, NodeId};
|
||||
use syntax::attr;
|
||||
use syntax::parse::token;
|
||||
use type_of;
|
||||
|
||||
|
||||
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
|
||||
pub enum TransItem<'tcx> {
|
||||
|
@ -54,6 +58,153 @@ impl<'tcx> Hash for TransItem<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
impl<'tcx> TransItem<'tcx> {
|
||||
|
||||
pub fn predefine<'ccx>(&self,
|
||||
ccx: &CrateContext<'ccx, 'tcx>,
|
||||
linkage: llvm::Linkage) {
|
||||
match *self {
|
||||
TransItem::Static(node_id) => {
|
||||
TransItem::predefine_static(ccx, node_id, linkage);
|
||||
}
|
||||
_ => {
|
||||
// Not yet implemented
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn predefine_static<'a>(ccx: &CrateContext<'a, 'tcx>,
|
||||
node_id: ast::NodeId,
|
||||
linkage: llvm::Linkage) {
|
||||
let def_id = ccx.tcx().map.local_def_id(node_id);
|
||||
let ty = ccx.tcx().lookup_item_type(def_id).ty;
|
||||
let llty = type_of::type_of(ccx, ty);
|
||||
|
||||
match ccx.tcx().map.get(node_id) {
|
||||
hir::map::NodeItem(&hir::Item {
|
||||
span, node: hir::ItemStatic(..), ..
|
||||
}) => {
|
||||
let instance = Instance::mono(ccx.shared(), def_id);
|
||||
let sym = instance.symbol_name(ccx.shared());
|
||||
debug!("making {}", sym);
|
||||
|
||||
let g = declare::define_global(ccx, &sym, llty).unwrap_or_else(|| {
|
||||
ccx.sess().span_fatal(span,
|
||||
&format!("symbol `{}` is already defined", sym))
|
||||
});
|
||||
|
||||
llvm::SetLinkage(g, linkage);
|
||||
}
|
||||
|
||||
item => bug!("predefine_static: expected static, found {:?}", item)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn requests_inline<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> bool {
|
||||
match *self {
|
||||
TransItem::Fn(ref instance) => {
|
||||
let attributes = tcx.get_attrs(instance.def);
|
||||
attr::requests_inline(&attributes[..])
|
||||
}
|
||||
TransItem::DropGlue(..) => true,
|
||||
TransItem::Static(..) => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_from_extern_crate(&self) -> bool {
|
||||
match *self {
|
||||
TransItem::Fn(ref instance) => !instance.def.is_local(),
|
||||
TransItem::DropGlue(..) |
|
||||
TransItem::Static(..) => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_lazily_instantiated(&self) -> bool {
|
||||
match *self {
|
||||
TransItem::Fn(ref instance) => !instance.substs.types.is_empty(),
|
||||
TransItem::DropGlue(..) => true,
|
||||
TransItem::Static(..) => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn explicit_linkage<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option<llvm::Linkage> {
|
||||
let def_id = match *self {
|
||||
TransItem::Fn(ref instance) => instance.def,
|
||||
TransItem::Static(node_id) => tcx.map.local_def_id(node_id),
|
||||
TransItem::DropGlue(..) => return None,
|
||||
};
|
||||
|
||||
let attributes = tcx.get_attrs(def_id);
|
||||
if let Some(name) = attr::first_attr_value_str_by_name(&attributes, "linkage") {
|
||||
if let Some(linkage) = base::llvm_linkage_by_name(&name) {
|
||||
Some(linkage)
|
||||
} else {
|
||||
let span = tcx.map.span_if_local(def_id);
|
||||
if let Some(span) = span {
|
||||
tcx.sess.span_fatal(span, "invalid linkage specified")
|
||||
} else {
|
||||
tcx.sess.fatal(&format!("invalid linkage specified: {}", name))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_string<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> String {
|
||||
let hir_map = &tcx.map;
|
||||
|
||||
return match *self {
|
||||
TransItem::DropGlue(dg) => {
|
||||
let mut s = String::with_capacity(32);
|
||||
match dg {
|
||||
DropGlueKind::Ty(_) => s.push_str("drop-glue "),
|
||||
DropGlueKind::TyContents(_) => s.push_str("drop-glue-contents "),
|
||||
};
|
||||
push_unique_type_name(tcx, dg.ty(), &mut s);
|
||||
s
|
||||
}
|
||||
TransItem::Fn(instance) => {
|
||||
to_string_internal(tcx, "fn ", instance)
|
||||
},
|
||||
TransItem::Static(node_id) => {
|
||||
let def_id = hir_map.local_def_id(node_id);
|
||||
let instance = Instance::new(def_id,
|
||||
tcx.mk_substs(subst::Substs::empty()));
|
||||
to_string_internal(tcx, "static ", instance)
|
||||
},
|
||||
};
|
||||
|
||||
fn to_string_internal<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx,'tcx>,
|
||||
prefix: &str,
|
||||
instance: Instance<'tcx>)
|
||||
-> String {
|
||||
let mut result = String::with_capacity(32);
|
||||
result.push_str(prefix);
|
||||
push_instance_as_string(tcx, instance, &mut result);
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_raw_string(&self) -> String {
|
||||
match *self {
|
||||
TransItem::DropGlue(dg) => {
|
||||
format!("DropGlue({})", dg.ty() as *const _ as usize)
|
||||
}
|
||||
TransItem::Fn(instance) => {
|
||||
format!("Fn({:?}, {})",
|
||||
instance.def,
|
||||
instance.substs as *const _ as usize)
|
||||
}
|
||||
TransItem::Static(id) => {
|
||||
format!("Static({:?})", id)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//=-----------------------------------------------------------------------------
|
||||
// TransItem String Keys
|
||||
//=-----------------------------------------------------------------------------
|
||||
|
@ -277,108 +428,3 @@ pub fn type_to_string<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
push_unique_type_name(tcx, ty, &mut output);
|
||||
output
|
||||
}
|
||||
|
||||
impl<'tcx> TransItem<'tcx> {
|
||||
|
||||
pub fn requests_inline<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> bool {
|
||||
match *self {
|
||||
TransItem::Fn(ref instance) => {
|
||||
let attributes = tcx.get_attrs(instance.def);
|
||||
attr::requests_inline(&attributes[..])
|
||||
}
|
||||
TransItem::DropGlue(..) => true,
|
||||
TransItem::Static(..) => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_from_extern_crate(&self) -> bool {
|
||||
match *self {
|
||||
TransItem::Fn(ref instance) => !instance.def.is_local(),
|
||||
TransItem::DropGlue(..) |
|
||||
TransItem::Static(..) => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_lazily_instantiated(&self) -> bool {
|
||||
match *self {
|
||||
TransItem::Fn(ref instance) => !instance.substs.types.is_empty(),
|
||||
TransItem::DropGlue(..) => true,
|
||||
TransItem::Static(..) => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn explicit_linkage<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option<llvm::Linkage> {
|
||||
let def_id = match *self {
|
||||
TransItem::Fn(ref instance) => instance.def,
|
||||
TransItem::Static(node_id) => tcx.map.local_def_id(node_id),
|
||||
TransItem::DropGlue(..) => return None,
|
||||
};
|
||||
|
||||
let attributes = tcx.get_attrs(def_id);
|
||||
if let Some(name) = attr::first_attr_value_str_by_name(&attributes, "linkage") {
|
||||
if let Some(linkage) = llvm_linkage_by_name(&name) {
|
||||
Some(linkage)
|
||||
} else {
|
||||
let span = tcx.map.span_if_local(def_id);
|
||||
if let Some(span) = span {
|
||||
tcx.sess.span_fatal(span, "invalid linkage specified")
|
||||
} else {
|
||||
tcx.sess.fatal(&format!("invalid linkage specified: {}", name))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_string<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> String {
|
||||
let hir_map = &tcx.map;
|
||||
|
||||
return match *self {
|
||||
TransItem::DropGlue(dg) => {
|
||||
let mut s = String::with_capacity(32);
|
||||
match dg {
|
||||
DropGlueKind::Ty(_) => s.push_str("drop-glue "),
|
||||
DropGlueKind::TyContents(_) => s.push_str("drop-glue-contents "),
|
||||
};
|
||||
push_unique_type_name(tcx, dg.ty(), &mut s);
|
||||
s
|
||||
}
|
||||
TransItem::Fn(instance) => {
|
||||
to_string_internal(tcx, "fn ", instance)
|
||||
},
|
||||
TransItem::Static(node_id) => {
|
||||
let def_id = hir_map.local_def_id(node_id);
|
||||
let empty_substs = tcx.mk_substs(subst::Substs::empty());
|
||||
let instance = Instance::new(def_id, empty_substs);
|
||||
to_string_internal(tcx, "static ", instance)
|
||||
},
|
||||
};
|
||||
|
||||
fn to_string_internal<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
prefix: &str,
|
||||
instance: Instance<'tcx>)
|
||||
-> String {
|
||||
let mut result = String::with_capacity(32);
|
||||
result.push_str(prefix);
|
||||
push_instance_as_string(tcx, instance, &mut result);
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_raw_string(&self) -> String {
|
||||
match *self {
|
||||
TransItem::DropGlue(dg) => {
|
||||
format!("DropGlue({})", dg.ty() as *const _ as usize)
|
||||
}
|
||||
TransItem::Fn(instance) => {
|
||||
format!("Fn({:?}, {})",
|
||||
instance.def,
|
||||
instance.substs as *const _ as usize)
|
||||
}
|
||||
TransItem::Static(id) => {
|
||||
format!("Static({:?})", id)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue