From 5af3c12cfc07887b66ed1d8cd9e59e1c77cc8790 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Tue, 23 Feb 2016 21:39:35 +0200 Subject: [PATCH] trans: Move static item handling to consts. --- src/librustc_trans/trans/base.rs | 63 ++--------------- src/librustc_trans/trans/closure.rs | 2 +- src/librustc_trans/trans/common.rs | 11 --- src/librustc_trans/trans/consts.rs | 98 +++++++++++++++++++++----- src/librustc_trans/trans/expr.rs | 94 +++++++++--------------- src/librustc_trans/trans/mir/lvalue.rs | 5 +- 6 files changed, 123 insertions(+), 150 deletions(-) diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs index 8094434845f..b189384b7d0 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -10,8 +10,8 @@ //! Translate the completed AST to the LLVM IR. //! //! Some functions here, such as trans_block and trans_expr, return a value -- -//! the result of the translation to LLVM -- while others, such as trans_fn, -//! trans_impl, and trans_item, are called only for the side effect of adding a +//! the result of the translation to LLVM -- while others, such as trans_fn +//! and trans_item, are called only for the side effect of adding a //! particular definition to the LLVM IR output we're producing. //! //! Hopefully useful general knowledge about trans: @@ -228,36 +228,6 @@ pub fn kind_for_closure(ccx: &CrateContext, closure_id: DefId) -> ty::ClosureKin *ccx.tcx().tables.borrow().closure_kinds.get(&closure_id).unwrap() } -pub fn get_extern_const<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, - did: DefId, - t: Ty<'tcx>) - -> ValueRef { - let name = ccx.sess().cstore.item_symbol(did); - let ty = type_of(ccx, t); - if let Some(n) = ccx.externs().borrow_mut().get(&name) { - return *n; - } - // FIXME(nagisa): perhaps the map of externs could be offloaded to llvm somehow? - // FIXME(nagisa): investigate whether it can be changed into define_global - let c = declare::declare_global(ccx, &name[..], ty); - // Thread-local statics in some other crate need to *always* be linked - // against in a thread-local fashion, so we need to be sure to apply the - // thread-local attribute locally if it was present remotely. If we - // don't do this then linker errors can be generated where the linker - // complains that one object files has a thread local version of the - // symbol and another one doesn't. - for attr in ccx.tcx().get_attrs(did).iter() { - if attr.check_name("thread_local") { - llvm::set_thread_local(c, true); - } - } - if ccx.use_dll_storage_attrs() { - llvm::SetDLLStorageClass(c, llvm::DLLImportStorageClass); - } - ccx.externs().borrow_mut().insert(name.to_string(), c); - return c; -} - fn require_alloc_fn<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, info_ty: Ty<'tcx>, it: LangItem) -> DefId { match bcx.tcx().lang_items.require(it) { Ok(id) => id, @@ -2714,11 +2684,11 @@ fn create_entry_fn(ccx: &CrateContext, } } -fn exported_name<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, - id: ast::NodeId, - ty: Ty<'tcx>, - attrs: &[ast::Attribute]) - -> String { +pub fn exported_name<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, + id: ast::NodeId, + ty: Ty<'tcx>, + attrs: &[ast::Attribute]) + -> String { match ccx.external_srcs().borrow().get(&id) { Some(&did) => { let sym = ccx.sess().cstore.item_symbol(did); @@ -2768,25 +2738,6 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef { let sym = || exported_name(ccx, id, ty, &i.attrs); let v = match i.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 - let sym = sym(); - debug!("making {}", sym); - - // Create the global before evaluating the initializer; - // this is necessary to allow recursive statics. - let llty = type_of(ccx, ty); - let g = declare::define_global(ccx, &sym[..], llty).unwrap_or_else(|| { - ccx.sess() - .span_fatal(i.span, &format!("symbol `{}` is already defined", sym)) - }); - - ccx.item_symbols().borrow_mut().insert(i.id, sym); - g - } hir::ItemFn(_, _, _, abi, _, _) => { let sym = sym(); diff --git a/src/librustc_trans/trans/closure.rs b/src/librustc_trans/trans/closure.rs index 0eb4def89e8..eb050c43fa5 100644 --- a/src/librustc_trans/trans/closure.rs +++ b/src/librustc_trans/trans/closure.rs @@ -241,7 +241,7 @@ pub fn trans_closure_expr<'a, 'tcx>(dest: Dest<'a, 'tcx>, // Create the closure. for (i, freevar) in freevars.iter().enumerate() { - let datum = expr::trans_local_var(bcx, freevar.def); + let datum = expr::trans_var(bcx, freevar.def); let upvar_slot_dest = adt::trans_field_ptr( bcx, &repr, adt::MaybeSizedValue::sized(dest_addr), Disr(0), i); let upvar_id = ty::UpvarId { var_id: freevar.def.var_id(), diff --git a/src/librustc_trans/trans/common.rs b/src/librustc_trans/trans/common.rs index c974173f765..165a213a91e 100644 --- a/src/librustc_trans/trans/common.rs +++ b/src/librustc_trans/trans/common.rs @@ -1341,14 +1341,3 @@ pub fn shift_mask_val<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, _ => panic!("shift_mask_val: expected Integer or Vector, found {:?}", kind), } } - -pub fn get_static_val<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, - did: DefId, - ty: Ty<'tcx>) - -> ValueRef { - if let Some(node_id) = ccx.tcx().map.as_local_node_id(did) { - base::get_item_val(ccx, node_id) - } else { - base::get_extern_const(ccx, did, ty) - } -} diff --git a/src/librustc_trans/trans/consts.rs b/src/librustc_trans/trans/consts.rs index ec550c680de..35e2646a1ab 100644 --- a/src/librustc_trans/trans/consts.rs +++ b/src/librustc_trans/trans/consts.rs @@ -18,16 +18,19 @@ use middle::const_eval::{self, ConstEvalErr}; use middle::def::Def; use middle::def_id::DefId; +use rustc::front::map as hir_map; use trans::{adt, closure, debuginfo, expr, inline, machine}; -use trans::base::{self, push_ctxt}; +use trans::base::{self, exported_name, push_ctxt}; use trans::callee::Callee; use trans::collector::{self, TransItem}; use trans::common::{self, type_is_sized, ExprOrMethodCall, node_id_substs, C_nil, const_get_elt}; use trans::common::{CrateContext, C_integral, C_floating, C_bool, C_str_slice, C_bytes, val_ty}; use trans::common::{C_struct, C_undef, const_to_opt_int, const_to_opt_uint, VariantInfo, C_uint}; use trans::common::{type_is_fat_ptr, Field, C_vector, C_array, C_null, ExprId, MethodCallKey}; +use trans::datum::{Datum, Lvalue}; use trans::declare; use trans::monomorphize; +use trans::foreign; use trans::type_::Type; use trans::type_of; use trans::value::Value; @@ -46,7 +49,7 @@ use std::borrow::Cow; use libc::c_uint; use syntax::ast::{self, LitKind}; -use syntax::attr; +use syntax::attr::{self, AttrMetaMethods}; use syntax::parse::token; use syntax::ptr::P; @@ -806,7 +809,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, } let opt_def = cx.tcx().def_map.borrow().get(&cur.id).map(|d| d.full_def()); if let Some(Def::Static(def_id, _)) = opt_def { - common::get_static_val(cx, def_id, ety) + get_static(cx, def_id).val } else { // If this isn't the address of a static, then keep going through // normal constant evaluation. @@ -1013,6 +1016,65 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, }) } +pub fn get_static<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, def_id: DefId) + -> Datum<'tcx, Lvalue> { + let ty = ccx.tcx().lookup_item_type(def_id).ty; + + let g = if let Some(id) = ccx.tcx().map.as_local_node_id(def_id) { + match ccx.tcx().map.get(id) { + hir_map::NodeItem(&hir::Item { + 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 + let sym = exported_name(ccx, id, ty, attrs); + debug!("making {}", sym); + + // Create the global before evaluating the initializer; + // this is necessary to allow recursive statics. + let llty = type_of::type_of(ccx, ty); + let g = declare::define_global(ccx, &sym, llty).unwrap_or_else(|| { + ccx.sess().span_fatal(span, + &format!("symbol `{}` is already defined", sym)) + }); + + ccx.item_symbols().borrow_mut().insert(id, sym); + g + } + + hir_map::NodeForeignItem(ni @ &hir::ForeignItem { + node: hir::ForeignItemStatic(..), .. + }) => foreign::register_static(ccx, ni), + + item => unreachable!("get_static: expected static, found {:?}", item) + } + } 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 + let name = ccx.sess().cstore.item_symbol(def_id); + let g = declare::declare_global(ccx, &name, type_of::type_of(ccx, ty)); + // Thread-local statics in some other crate need to *always* be linked + // against in a thread-local fashion, so we need to be sure to apply the + // thread-local attribute locally if it was present remotely. If we + // don't do this then linker errors can be generated where the linker + // complains that one object files has a thread local version of the + // symbol and another one doesn't. + for attr in ccx.tcx().get_attrs(def_id).iter() { + if attr.check_name("thread_local") { + llvm::set_thread_local(g, true); + } + } + if ccx.use_dll_storage_attrs() { + llvm::SetDLLStorageClass(g, llvm::DLLImportStorageClass); + } + g + }; + + Datum::new(g, ty, Lvalue::new("static")) +} + pub fn trans_static(ccx: &CrateContext, m: hir::Mutability, expr: &hir::Expr, @@ -1026,7 +1088,8 @@ pub fn trans_static(ccx: &CrateContext, unsafe { let _icx = push_ctxt("trans_static"); - let g = base::get_item_val(ccx, id); + let def_id = ccx.tcx().map.local_def_id(id); + let datum = get_static(ccx, def_id); let empty_substs = ccx.tcx().mk_substs(Substs::trans_empty()); let (v, _) = try!(const_expr( @@ -1039,40 +1102,39 @@ pub fn trans_static(ccx: &CrateContext, // 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 = llvm::LLVMTypeOf(v); - let v = if val_llty == Type::i1(ccx).to_ref() { - val_llty = Type::i8(ccx).to_ref(); - llvm::LLVMConstZExt(v, val_llty) + let mut val_llty = val_ty(v); + let v = if val_llty == Type::i1(ccx) { + val_llty = Type::i8(ccx); + llvm::LLVMConstZExt(v, val_llty.to_ref()) } else { v }; - let ty = ccx.tcx().node_id_to_type(id); - let llty = type_of::type_of(ccx, ty); - let g = if val_llty == llty.to_ref() { - g + let llty = type_of::type_of(ccx, datum.ty); + let g = if val_llty == llty { + datum.val } else { // If we created the global with the wrong type, // correct the type. let empty_string = CString::new("").unwrap(); - let name_str_ref = CStr::from_ptr(llvm::LLVMGetValueName(g)); + let name_str_ref = CStr::from_ptr(llvm::LLVMGetValueName(datum.val)); let name_string = CString::new(name_str_ref.to_bytes()).unwrap(); - llvm::LLVMSetValueName(g, empty_string.as_ptr()); + llvm::LLVMSetValueName(datum.val, empty_string.as_ptr()); let new_g = llvm::LLVMGetOrInsertGlobal( - ccx.llmod(), name_string.as_ptr(), val_llty); + ccx.llmod(), name_string.as_ptr(), val_llty.to_ref()); // To avoid breaking any invariants, we leave around the old // global for the moment; we'll replace all references to it // with the new global later. (See base::trans_crate.) - ccx.statics_to_rauw().borrow_mut().push((g, new_g)); + ccx.statics_to_rauw().borrow_mut().push((datum.val, new_g)); new_g }; - llvm::LLVMSetAlignment(g, type_of::align_of(ccx, ty)); + llvm::LLVMSetAlignment(g, type_of::align_of(ccx, datum.ty)); llvm::LLVMSetInitializer(g, v); // As an optimization, all shared statics which do not have interior // mutability are placed into read-only memory. if m != hir::MutMutable { - let tcontents = ty.type_contents(ccx.tcx()); + let tcontents = datum.ty.type_contents(ccx.tcx()); if !tcontents.interior_unsafe() { llvm::LLVMSetGlobalConstant(g, llvm::True); } diff --git a/src/librustc_trans/trans/expr.rs b/src/librustc_trans/trans/expr.rs index 63612cd1e1f..65fd271d74a 100644 --- a/src/librustc_trans/trans/expr.rs +++ b/src/librustc_trans/trans/expr.rs @@ -44,7 +44,7 @@ //! expression and ensures that the result has a cleanup associated with it, //! creating a temporary stack slot if necessary. //! -//! - `trans_local_var -> Datum`: looks up a local variable or upvar. +//! - `trans_var -> Datum`: looks up a local variable, upvar or static. #![allow(non_camel_case_types)] @@ -652,7 +652,8 @@ fn trans_datum_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, trans(bcx, &e) } hir::ExprPath(..) => { - trans_def(bcx, expr, bcx.def(expr.id)) + let var = trans_var(bcx, bcx.def(expr.id)); + DatumBlock::new(bcx, var.to_expr_datum()) } hir::ExprField(ref base, name) => { trans_rec_field(bcx, &base, name.node) @@ -882,27 +883,40 @@ fn trans_index<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, DatumBlock::new(bcx, elt_datum) } -fn trans_def<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, - ref_expr: &hir::Expr, - def: Def) - -> DatumBlock<'blk, 'tcx, Expr> { - //! Translates a reference to a path. +/// Translates a reference to a variable. +pub fn trans_var<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, def: Def) + -> Datum<'tcx, Lvalue> { - let _icx = push_ctxt("trans_def_lvalue"); match def { - Def::Static(did, _) => { - let const_ty = expr_ty(bcx, ref_expr); - let val = get_static_val(bcx.ccx(), did, const_ty); - let lval = Lvalue::new("expr::trans_def"); - DatumBlock::new(bcx, Datum::new(val, const_ty, LvalueExpr(lval))) - } - Def::Local(..) | Def::Upvar(..) => { - DatumBlock::new(bcx, trans_local_var(bcx, def).to_expr_datum()) + Def::Static(did, _) => consts::get_static(bcx.ccx(), did), + Def::Upvar(_, nid, _, _) => { + // Can't move upvars, so this is never a ZeroMemLastUse. + let local_ty = node_id_type(bcx, nid); + let lval = Lvalue::new_with_hint("expr::trans_var (upvar)", + bcx, nid, HintKind::ZeroAndMaintain); + match bcx.fcx.llupvars.borrow().get(&nid) { + Some(&val) => Datum::new(val, local_ty, lval), + None => { + bcx.sess().bug(&format!( + "trans_var: no llval for upvar {} found", + nid)); + } + } } - _ => { - bcx.sess().span_bug(ref_expr.span, - &format!("{:?} should not reach expr::trans_def", def)) + Def::Local(_, nid) => { + let datum = match bcx.fcx.lllocals.borrow().get(&nid) { + Some(&v) => v, + None => { + bcx.sess().bug(&format!( + "trans_var: no datum for local/arg {} found", + nid)); + } + }; + debug!("take_local(nid={}, v={:?}, ty={})", + nid, Value(datum.val), datum.ty); + datum } + _ => unreachable!("{:?} should not reach expr::trans_var", def) } } @@ -1247,48 +1261,6 @@ fn trans_def_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } } -/// Translates a reference to a local variable or argument. This always results in an lvalue datum. -pub fn trans_local_var<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, - def: Def) - -> Datum<'tcx, Lvalue> { - let _icx = push_ctxt("trans_local_var"); - - match def { - Def::Upvar(_, nid, _, _) => { - // Can't move upvars, so this is never a ZeroMemLastUse. - let local_ty = node_id_type(bcx, nid); - let lval = Lvalue::new_with_hint("expr::trans_local_var (upvar)", - bcx, nid, HintKind::ZeroAndMaintain); - match bcx.fcx.llupvars.borrow().get(&nid) { - Some(&val) => Datum::new(val, local_ty, lval), - None => { - bcx.sess().bug(&format!( - "trans_local_var: no llval for upvar {} found", - nid)); - } - } - } - Def::Local(_, nid) => { - let datum = match bcx.fcx.lllocals.borrow().get(&nid) { - Some(&v) => v, - None => { - bcx.sess().bug(&format!( - "trans_local_var: no datum for local/arg {} found", - nid)); - } - }; - debug!("take_local(nid={}, v={:?}, ty={})", - nid, Value(datum.val), datum.ty); - datum - } - _ => { - bcx.sess().unimpl(&format!( - "unsupported def type in trans_local_var: {:?}", - def)); - } - } -} - fn trans_struct<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, fields: &[hir::Field], base: Option<&hir::Expr>, diff --git a/src/librustc_trans/trans/mir/lvalue.rs b/src/librustc_trans/trans/mir/lvalue.rs index 8d97708ca26..14a36c42e6d 100644 --- a/src/librustc_trans/trans/mir/lvalue.rs +++ b/src/librustc_trans/trans/mir/lvalue.rs @@ -15,6 +15,7 @@ use trans::adt; use trans::base; use trans::common::{self, BlockAndBuilder}; +use trans::consts; use trans::machine; use trans::type_of; use trans::mir::drop; @@ -89,9 +90,7 @@ pub fn trans_lvalue(&mut self, mir::Lvalue::Arg(index) => self.args[index as usize], mir::Lvalue::Static(def_id) => { let const_ty = self.mir.lvalue_ty(tcx, lvalue); - LvalueRef::new_sized( - common::get_static_val(ccx, def_id, const_ty.to_ty(tcx)), - const_ty) + LvalueRef::new_sized(consts::get_static(ccx, def_id).val, const_ty) }, mir::Lvalue::ReturnPointer => { let fn_return_ty = bcx.monomorphize(&self.mir.return_ty); -- GitLab