mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-26 00:34:06 +00:00
Make drop-glue translation collector-driven.
This commit is contained in:
parent
6c8c94b848
commit
87c1c87dd7
@ -229,6 +229,7 @@ impl ArgType {
|
||||
///
|
||||
/// I will do my best to describe this structure, but these
|
||||
/// comments are reverse-engineered and may be inaccurate. -NDM
|
||||
#[derive(Clone)]
|
||||
pub struct FnType {
|
||||
/// The LLVM types of each argument.
|
||||
pub args: Vec<ArgType>,
|
||||
|
@ -304,6 +304,19 @@ impl ItemPathBuffer for SymbolPathBuffer {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn exported_name_from_type_and_prefix<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
|
||||
t: ty::Ty<'tcx>,
|
||||
prefix: &str)
|
||||
-> String {
|
||||
let empty_def_path = DefPath {
|
||||
data: vec![],
|
||||
krate: cstore::LOCAL_CRATE,
|
||||
};
|
||||
let hash = get_symbol_hash(scx, &empty_def_path, t, &[]);
|
||||
let path = [token::intern_and_get_ident(prefix)];
|
||||
mangle(path.iter().cloned(), Some(&hash[..]))
|
||||
}
|
||||
|
||||
/// Only symbols that are invisible outside their compilation unit should use a
|
||||
/// name generated by this function.
|
||||
pub fn internal_name_from_type_and_suffix<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||
|
@ -2182,52 +2182,6 @@ pub fn llvm_linkage_by_name(name: &str) -> Option<Linkage> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the appropriate linkage for an LLVM `ValueRef` (function or global).
|
||||
/// If the `llval` is the direct translation of a specific Rust item, `id`
|
||||
/// should be set to the `NodeId` of that item. (This mapping should be
|
||||
/// 1-to-1, so monomorphizations and drop/visit glue should have `id` set to
|
||||
/// `None`.)
|
||||
pub fn update_linkage(ccx: &CrateContext,
|
||||
llval: ValueRef,
|
||||
id: Option<ast::NodeId>) {
|
||||
if let Some(id) = id {
|
||||
let item = ccx.tcx().map.get(id);
|
||||
if let hir_map::NodeItem(i) = item {
|
||||
if let Some(name) = attr::first_attr_value_str_by_name(&i.attrs, "linkage") {
|
||||
if let Some(linkage) = llvm_linkage_by_name(&name) {
|
||||
llvm::SetLinkage(llval, linkage);
|
||||
} else {
|
||||
ccx.sess().span_fatal(i.span, "invalid linkage specified");
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let (is_reachable, is_generic) = if let Some(id) = id {
|
||||
(ccx.reachable().contains(&id), false)
|
||||
} else {
|
||||
(false, true)
|
||||
};
|
||||
|
||||
// We need external linkage for items reachable from other translation units, this include
|
||||
// other codegen units in case of parallel compilations.
|
||||
if is_reachable || ccx.sess().opts.cg.codegen_units > 1 {
|
||||
if is_generic {
|
||||
// This only happens with multiple codegen units, in which case we need to use weak_odr
|
||||
// linkage because other crates might expose the same symbol. We cannot use
|
||||
// linkonce_odr here because the symbol might then get dropped before the other codegen
|
||||
// units get to link it.
|
||||
llvm::SetUniqueComdat(ccx.llmod(), llval);
|
||||
llvm::SetLinkage(llval, llvm::WeakODRLinkage);
|
||||
} else {
|
||||
llvm::SetLinkage(llval, llvm::ExternalLinkage);
|
||||
}
|
||||
} else {
|
||||
llvm::SetLinkage(llval, llvm::InternalLinkage);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_link_section(ccx: &CrateContext,
|
||||
llval: ValueRef,
|
||||
attrs: &[ast::Attribute]) {
|
||||
@ -2673,24 +2627,8 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
|
||||
// ... 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")
|
||||
}
|
||||
}
|
||||
TransItem::Fn(instance) => {
|
||||
trans_instance(&ccx, instance);
|
||||
}
|
||||
_ => { }
|
||||
}
|
||||
for (trans_item, _) in &ccx.codegen_unit().items {
|
||||
trans_item.define(&ccx);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2927,7 +2865,7 @@ fn collect_and_partition_translation_items<'a, 'tcx>(scx: &SharedCrateContext<'a
|
||||
let mut item_keys: Vec<_> = items
|
||||
.iter()
|
||||
.map(|i| {
|
||||
let mut output = i.to_string(scx);
|
||||
let mut output = i.to_string(scx.tcx());
|
||||
output.push_str(" @@");
|
||||
let mut empty = Vec::new();
|
||||
let mut cgus = item_to_cgus.get_mut(i).unwrap_or(&mut empty);
|
||||
|
@ -325,7 +325,7 @@ fn collect_items_rec<'a, 'tcx: 'a>(scx: &SharedCrateContext<'a, 'tcx>,
|
||||
// We've been here already, no need to search again.
|
||||
return;
|
||||
}
|
||||
debug!("BEGIN collect_items_rec({})", starting_point.to_string(scx));
|
||||
debug!("BEGIN collect_items_rec({})", starting_point.to_string(scx.tcx()));
|
||||
|
||||
let mut neighbors = Vec::new();
|
||||
let recursion_depth_reset;
|
||||
@ -396,7 +396,7 @@ fn collect_items_rec<'a, 'tcx: 'a>(scx: &SharedCrateContext<'a, 'tcx>,
|
||||
recursion_depths.insert(def_id, depth);
|
||||
}
|
||||
|
||||
debug!("END collect_items_rec({})", starting_point.to_string(scx));
|
||||
debug!("END collect_items_rec({})", starting_point.to_string(scx.tcx()));
|
||||
}
|
||||
|
||||
fn record_inlining_canditates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
@ -637,7 +637,8 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
|
||||
let operand_ty = monomorphize::apply_param_substs(tcx,
|
||||
self.param_substs,
|
||||
&mt.ty);
|
||||
self.output.push(TransItem::DropGlue(DropGlueKind::Ty(operand_ty)));
|
||||
let ty = glue::get_drop_glue_type(tcx, operand_ty);
|
||||
self.output.push(TransItem::DropGlue(DropGlueKind::Ty(ty)));
|
||||
} else {
|
||||
bug!("Has the drop_in_place() intrinsic's signature changed?")
|
||||
}
|
||||
@ -1271,7 +1272,7 @@ pub fn print_collection_results<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>) {
|
||||
let mut item_keys = FnvHashMap();
|
||||
|
||||
for (item, item_state) in trans_items.iter() {
|
||||
let k = item.to_string(scx);
|
||||
let k = item.to_string(scx.tcx());
|
||||
|
||||
if item_keys.contains_key(&k) {
|
||||
let prev: (TransItem, TransItemState) = item_keys[&k];
|
||||
@ -1299,7 +1300,7 @@ pub fn print_collection_results<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>) {
|
||||
let mut generated = FnvHashSet();
|
||||
|
||||
for (item, item_state) in trans_items.iter() {
|
||||
let item_key = item.to_string(scx);
|
||||
let item_key = item.to_string(scx.tcx());
|
||||
|
||||
match *item_state {
|
||||
TransItemState::PredictedAndGenerated => {
|
||||
|
@ -36,7 +36,7 @@ use rustc::ty::{self, Ty, TyCtxt};
|
||||
use session::config::NoDebugInfo;
|
||||
use session::Session;
|
||||
use util::sha2::Sha256;
|
||||
use util::nodemap::{NodeMap, NodeSet, DefIdMap, FnvHashMap, FnvHashSet};
|
||||
use util::nodemap::{NodeMap, NodeSet, DefIdMap, FnvHashMap};
|
||||
|
||||
use std::ffi::{CStr, CString};
|
||||
use std::cell::{Cell, RefCell};
|
||||
@ -46,6 +46,7 @@ use std::rc::Rc;
|
||||
use std::str;
|
||||
use syntax::ast;
|
||||
use syntax::parse::token::InternedString;
|
||||
use abi::FnType;
|
||||
|
||||
pub struct Stats {
|
||||
pub n_glues_created: Cell<usize>,
|
||||
@ -80,8 +81,6 @@ pub struct SharedCrateContext<'a, 'tcx: 'a> {
|
||||
mir_map: &'a MirMap<'tcx>,
|
||||
mir_cache: RefCell<DefIdMap<Rc<mir::Mir<'tcx>>>>,
|
||||
|
||||
available_monomorphizations: RefCell<FnvHashSet<String>>,
|
||||
available_drop_glues: RefCell<FnvHashMap<DropGlueKind<'tcx>, String>>,
|
||||
use_dll_storage_attrs: bool,
|
||||
|
||||
translation_items: RefCell<FnvHashMap<TransItem<'tcx>, TransItemState>>,
|
||||
@ -99,7 +98,7 @@ pub struct LocalCrateContext<'tcx> {
|
||||
codegen_unit: CodegenUnit<'tcx>,
|
||||
needs_unwind_cleanup_cache: RefCell<FnvHashMap<Ty<'tcx>, bool>>,
|
||||
fn_pointer_shims: RefCell<FnvHashMap<Ty<'tcx>, ValueRef>>,
|
||||
drop_glues: RefCell<FnvHashMap<DropGlueKind<'tcx>, ValueRef>>,
|
||||
drop_glues: RefCell<FnvHashMap<DropGlueKind<'tcx>, (ValueRef, FnType)>>,
|
||||
/// Track mapping of external ids to local items imported for inlining
|
||||
external: RefCell<DefIdMap<Option<ast::NodeId>>>,
|
||||
/// Backwards version of the `external` map (inlined items to where they
|
||||
@ -413,8 +412,6 @@ impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> {
|
||||
},
|
||||
check_overflow: check_overflow,
|
||||
check_drop_flag_for_sanity: check_drop_flag_for_sanity,
|
||||
available_monomorphizations: RefCell::new(FnvHashSet()),
|
||||
available_drop_glues: RefCell::new(FnvHashMap()),
|
||||
use_dll_storage_attrs: use_dll_storage_attrs,
|
||||
translation_items: RefCell::new(FnvHashMap()),
|
||||
trait_cache: RefCell::new(DepTrackingMap::new(tcx.dep_graph.clone())),
|
||||
@ -730,7 +727,8 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
|
||||
&self.local().fn_pointer_shims
|
||||
}
|
||||
|
||||
pub fn drop_glues<'a>(&'a self) -> &'a RefCell<FnvHashMap<DropGlueKind<'tcx>, ValueRef>> {
|
||||
pub fn drop_glues<'a>(&'a self)
|
||||
-> &'a RefCell<FnvHashMap<DropGlueKind<'tcx>, (ValueRef, FnType)>> {
|
||||
&self.local().drop_glues
|
||||
}
|
||||
|
||||
@ -816,14 +814,6 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
|
||||
&self.shared.stats
|
||||
}
|
||||
|
||||
pub fn available_monomorphizations<'a>(&'a self) -> &'a RefCell<FnvHashSet<String>> {
|
||||
&self.shared.available_monomorphizations
|
||||
}
|
||||
|
||||
pub fn available_drop_glues(&self) -> &RefCell<FnvHashMap<DropGlueKind<'tcx>, String>> {
|
||||
&self.shared.available_drop_glues
|
||||
}
|
||||
|
||||
pub fn int_type(&self) -> Type {
|
||||
self.local().int_type
|
||||
}
|
||||
|
@ -138,6 +138,20 @@ pub fn define_global(ccx: &CrateContext, name: &str, ty: Type) -> Option<ValueRe
|
||||
}
|
||||
}
|
||||
|
||||
/// Declare a Rust function with an intention to define it.
|
||||
///
|
||||
/// Use this function when you intend to define a function. This function will
|
||||
/// return panic if the name already has a definition associated with it. This
|
||||
/// can happen with #[no_mangle] or #[export_name], for example.
|
||||
pub fn define_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||
name: &str,
|
||||
fn_type: ty::Ty<'tcx>) -> ValueRef {
|
||||
if get_defined_value(ccx, name).is_some() {
|
||||
ccx.sess().fatal(&format!("symbol `{}` already defined", name))
|
||||
} else {
|
||||
declare_fn(ccx, name, fn_type)
|
||||
}
|
||||
}
|
||||
|
||||
/// Declare a Rust function with an intention to define it.
|
||||
///
|
||||
@ -147,13 +161,9 @@ pub fn define_global(ccx: &CrateContext, name: &str, ty: Type) -> Option<ValueRe
|
||||
pub fn define_internal_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||
name: &str,
|
||||
fn_type: ty::Ty<'tcx>) -> ValueRef {
|
||||
if get_defined_value(ccx, name).is_some() {
|
||||
ccx.sess().fatal(&format!("symbol `{}` already defined", name))
|
||||
} else {
|
||||
let llfn = declare_fn(ccx, name, fn_type);
|
||||
let llfn = define_fn(ccx, name, fn_type);
|
||||
llvm::SetLinkage(llfn, llvm::InternalLinkage);
|
||||
llfn
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -14,15 +14,12 @@
|
||||
|
||||
use std;
|
||||
|
||||
use attributes;
|
||||
use back::symbol_names;
|
||||
use llvm;
|
||||
use llvm::{ValueRef, get_param};
|
||||
use middle::lang_items::ExchangeFreeFnLangItem;
|
||||
use rustc::ty::subst::{Substs};
|
||||
use rustc::traits;
|
||||
use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
|
||||
use abi::{Abi, FnType};
|
||||
use adt;
|
||||
use adt::GetDtorType; // for tcx.dtor_type()
|
||||
use base::*;
|
||||
@ -33,7 +30,6 @@ use cleanup::CleanupMethods;
|
||||
use collector;
|
||||
use common::*;
|
||||
use debuginfo::DebugLoc;
|
||||
use declare;
|
||||
use expr;
|
||||
use machine::*;
|
||||
use monomorphize;
|
||||
@ -236,48 +232,21 @@ impl<'tcx> DropGlueKind<'tcx> {
|
||||
|
||||
fn get_drop_glue_core<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||
g: DropGlueKind<'tcx>) -> ValueRef {
|
||||
debug!("make drop glue for {:?}", g);
|
||||
let g = g.map_ty(|t| get_drop_glue_type(ccx.tcx(), t));
|
||||
debug!("drop glue type {:?}", g);
|
||||
match ccx.drop_glues().borrow().get(&g) {
|
||||
Some(&glue) => return glue,
|
||||
_ => { }
|
||||
Some(&(glue, _)) => glue,
|
||||
None => { bug!("Could not find drop glue for {:?} -- {} -- {}",
|
||||
g,
|
||||
TransItem::DropGlue(g).to_raw_string(),
|
||||
ccx.codegen_unit().name) }
|
||||
}
|
||||
let t = g.ty();
|
||||
}
|
||||
|
||||
pub fn implement_drop_glue<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||
g: DropGlueKind<'tcx>) {
|
||||
let tcx = ccx.tcx();
|
||||
let sig = ty::FnSig {
|
||||
inputs: vec![tcx.mk_mut_ptr(tcx.types.i8)],
|
||||
output: ty::FnOutput::FnConverging(tcx.mk_nil()),
|
||||
variadic: false,
|
||||
};
|
||||
// Create a FnType for fn(*mut i8) and substitute the real type in
|
||||
// later - that prevents FnType from splitting fat pointers up.
|
||||
let mut fn_ty = FnType::new(ccx, Abi::Rust, &sig, &[]);
|
||||
fn_ty.args[0].original_ty = type_of(ccx, t).ptr_to();
|
||||
let llfnty = fn_ty.llvm_type(ccx);
|
||||
|
||||
// To avoid infinite recursion, don't `make_drop_glue` until after we've
|
||||
// added the entry to the `drop_glues` cache.
|
||||
if let Some(old_sym) = ccx.available_drop_glues().borrow().get(&g) {
|
||||
let llfn = declare::declare_cfn(ccx, &old_sym, llfnty);
|
||||
ccx.drop_glues().borrow_mut().insert(g, llfn);
|
||||
return llfn;
|
||||
};
|
||||
|
||||
let suffix = match g {
|
||||
DropGlueKind::Ty(_) => "drop",
|
||||
DropGlueKind::TyContents(_) => "drop_contents",
|
||||
};
|
||||
|
||||
let fn_nm = symbol_names::internal_name_from_type_and_suffix(ccx, t, suffix);
|
||||
assert!(declare::get_defined_value(ccx, &fn_nm).is_none());
|
||||
let llfn = declare::declare_cfn(ccx, &fn_nm, llfnty);
|
||||
attributes::set_frame_pointer_elimination(ccx, llfn);
|
||||
ccx.available_drop_glues().borrow_mut().insert(g, fn_nm);
|
||||
ccx.drop_glues().borrow_mut().insert(g, llfn);
|
||||
|
||||
let _s = StatRecorder::new(ccx, format!("drop {:?}", t));
|
||||
assert_eq!(g.ty(), get_drop_glue_type(tcx, g.ty()));
|
||||
let (llfn, fn_ty) = ccx.drop_glues().borrow().get(&g).unwrap().clone();
|
||||
|
||||
let (arena, fcx): (TypedArena<_>, FunctionContext);
|
||||
arena = TypedArena::new();
|
||||
@ -285,8 +254,6 @@ fn get_drop_glue_core<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||
|
||||
let bcx = fcx.init(false, None);
|
||||
|
||||
update_linkage(ccx, llfn, None);
|
||||
|
||||
ccx.stats().n_glues_created.set(ccx.stats().n_glues_created.get() + 1);
|
||||
// All glue functions take values passed *by alias*; this is a
|
||||
// requirement since in many contexts glue is invoked indirectly and
|
||||
@ -298,10 +265,9 @@ fn get_drop_glue_core<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||
|
||||
let bcx = make_drop_glue(bcx, get_param(llfn, 0), g);
|
||||
fcx.finish(bcx, DebugLoc::None);
|
||||
|
||||
llfn
|
||||
}
|
||||
|
||||
|
||||
fn trans_struct_drop_flag<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
|
||||
t: Ty<'tcx>,
|
||||
struct_data: ValueRef)
|
||||
|
@ -165,10 +165,14 @@ pub fn partition<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
trans_items,
|
||||
reachable);
|
||||
|
||||
debug_dump(tcx, "INITIAL PARTITONING:", initial_partitioning.codegen_units.iter());
|
||||
|
||||
// If the partitioning should produce a fixed count of codegen units, merge
|
||||
// until that count is reached.
|
||||
if let PartitioningStrategy::FixedUnitCount(count) = strategy {
|
||||
merge_codegen_units(&mut initial_partitioning, count, &tcx.crate_name[..]);
|
||||
|
||||
debug_dump(tcx, "POST MERGING:", initial_partitioning.codegen_units.iter());
|
||||
}
|
||||
|
||||
// In the next step, we use the inlining map to determine which addtional
|
||||
@ -177,6 +181,9 @@ pub fn partition<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
// local functions the definition of which is marked with #[inline].
|
||||
let post_inlining = place_inlined_translation_items(initial_partitioning,
|
||||
inlining_map);
|
||||
|
||||
debug_dump(tcx, "POST INLINING:", post_inlining.0.iter());
|
||||
|
||||
post_inlining.0
|
||||
}
|
||||
|
||||
@ -484,3 +491,23 @@ fn numbered_codegen_unit_name(crate_name: &str, index: usize) -> InternedString
|
||||
NUMBERED_CODEGEN_UNIT_MARKER,
|
||||
index)[..])
|
||||
}
|
||||
|
||||
fn debug_dump<'a, 'b, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
label: &str,
|
||||
cgus: I)
|
||||
where I: Iterator<Item=&'b CodegenUnit<'tcx>>,
|
||||
'tcx: 'a + 'b
|
||||
{
|
||||
if cfg!(debug_assertions) {
|
||||
debug!("{}", label);
|
||||
for cgu in cgus {
|
||||
debug!("CodegenUnit {}:", cgu.name);
|
||||
|
||||
for (trans_item, linkage) in &cgu.items {
|
||||
debug!(" - {} [{:?}]", trans_item.to_string(tcx), linkage);
|
||||
}
|
||||
|
||||
debug!("");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,8 @@
|
||||
|
||||
use attributes;
|
||||
use base;
|
||||
use context::{SharedCrateContext, CrateContext};
|
||||
use consts;
|
||||
use context::CrateContext;
|
||||
use declare;
|
||||
use glue::DropGlueKind;
|
||||
use llvm;
|
||||
@ -32,7 +33,9 @@ use syntax::ast::{self, NodeId};
|
||||
use syntax::{attr,errors};
|
||||
use syntax::parse::token;
|
||||
use type_of;
|
||||
|
||||
use glue;
|
||||
use abi::{Abi, FnType};
|
||||
use back::symbol_names;
|
||||
|
||||
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
|
||||
pub enum TransItem<'tcx> {
|
||||
@ -64,9 +67,47 @@ impl<'tcx> Hash for TransItem<'tcx> {
|
||||
|
||||
impl<'a, 'tcx> TransItem<'tcx> {
|
||||
|
||||
pub fn define(&self, ccx: &CrateContext<'a, 'tcx>) {
|
||||
|
||||
debug!("BEGIN IMPLEMENTING '{} ({})' in cgu {}",
|
||||
self.to_string(ccx.tcx()),
|
||||
self.to_raw_string(),
|
||||
ccx.codegen_unit().name);
|
||||
|
||||
match *self {
|
||||
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")
|
||||
}
|
||||
}
|
||||
TransItem::Fn(instance) => {
|
||||
base::trans_instance(&ccx, instance);
|
||||
}
|
||||
TransItem::DropGlue(dg) => {
|
||||
glue::implement_drop_glue(&ccx, dg);
|
||||
}
|
||||
}
|
||||
|
||||
debug!("END IMPLEMENTING '{} ({})' in cgu {}",
|
||||
self.to_string(ccx.tcx()),
|
||||
self.to_raw_string(),
|
||||
ccx.codegen_unit().name);
|
||||
}
|
||||
|
||||
pub fn predefine(&self,
|
||||
ccx: &CrateContext<'a, 'tcx>,
|
||||
linkage: llvm::Linkage) {
|
||||
debug!("BEGIN PREDEFINING '{} ({})' in cgu {}",
|
||||
self.to_string(ccx.tcx()),
|
||||
self.to_raw_string(),
|
||||
ccx.codegen_unit().name);
|
||||
|
||||
match *self {
|
||||
TransItem::Static(node_id) => {
|
||||
TransItem::predefine_static(ccx, node_id, linkage);
|
||||
@ -74,10 +115,15 @@ impl<'a, 'tcx> TransItem<'tcx> {
|
||||
TransItem::Fn(instance) => {
|
||||
TransItem::predefine_fn(ccx, instance, linkage);
|
||||
}
|
||||
_ => {
|
||||
// Not yet implemented
|
||||
TransItem::DropGlue(dg) => {
|
||||
TransItem::predefine_drop_glue(ccx, dg, linkage);
|
||||
}
|
||||
}
|
||||
|
||||
debug!("END PREDEFINING '{} ({})' in cgu {}",
|
||||
self.to_string(ccx.tcx()),
|
||||
self.to_raw_string(),
|
||||
ccx.codegen_unit().name);
|
||||
}
|
||||
|
||||
fn predefine_static(ccx: &CrateContext<'a, 'tcx>,
|
||||
@ -93,7 +139,7 @@ impl<'a, 'tcx> TransItem<'tcx> {
|
||||
}) => {
|
||||
let instance = Instance::mono(ccx.shared(), def_id);
|
||||
let sym = instance.symbol_name(ccx.shared());
|
||||
debug!("making {}", sym);
|
||||
debug!("symbol {}", sym);
|
||||
|
||||
let g = declare::define_global(ccx, &sym, llty).unwrap_or_else(|| {
|
||||
ccx.sess().span_fatal(span,
|
||||
@ -110,8 +156,6 @@ impl<'a, 'tcx> TransItem<'tcx> {
|
||||
fn predefine_fn(ccx: &CrateContext<'a, 'tcx>,
|
||||
instance: Instance<'tcx>,
|
||||
linkage: llvm::Linkage) {
|
||||
let unit = ccx.codegen_unit();
|
||||
debug!("predefine_fn[cg={}](instance={:?})", &unit.name[..], instance);
|
||||
assert!(!instance.substs.types.needs_infer() &&
|
||||
!instance.substs.types.has_param_types());
|
||||
|
||||
@ -143,10 +187,11 @@ impl<'a, 'tcx> TransItem<'tcx> {
|
||||
ref attrs, node: hir::ImplItemKind::Method(..), ..
|
||||
}) => {
|
||||
let symbol = instance.symbol_name(ccx.shared());
|
||||
let lldecl = declare::declare_fn(ccx, &symbol, mono_ty);
|
||||
debug!("symbol {}", symbol);
|
||||
|
||||
attributes::from_fn_attrs(ccx, attrs, lldecl);
|
||||
let lldecl = declare::declare_fn(ccx, &symbol, mono_ty);
|
||||
llvm::SetLinkage(lldecl, linkage);
|
||||
attributes::from_fn_attrs(ccx, attrs, lldecl);
|
||||
base::set_link_section(ccx, lldecl, attrs);
|
||||
|
||||
ccx.instances().borrow_mut().insert(instance, lldecl);
|
||||
@ -156,6 +201,39 @@ impl<'a, 'tcx> TransItem<'tcx> {
|
||||
|
||||
}
|
||||
|
||||
fn predefine_drop_glue(ccx: &CrateContext<'a, 'tcx>,
|
||||
dg: glue::DropGlueKind<'tcx>,
|
||||
linkage: llvm::Linkage) {
|
||||
let tcx = ccx.tcx();
|
||||
assert_eq!(dg.ty(), glue::get_drop_glue_type(tcx, dg.ty()));
|
||||
let t = dg.ty();
|
||||
|
||||
let sig = ty::FnSig {
|
||||
inputs: vec![tcx.mk_mut_ptr(tcx.types.i8)],
|
||||
output: ty::FnOutput::FnConverging(tcx.mk_nil()),
|
||||
variadic: false,
|
||||
};
|
||||
|
||||
// Create a FnType for fn(*mut i8) and substitute the real type in
|
||||
// later - that prevents FnType from splitting fat pointers up.
|
||||
let mut fn_ty = FnType::new(ccx, Abi::Rust, &sig, &[]);
|
||||
fn_ty.args[0].original_ty = type_of::type_of(ccx, t).ptr_to();
|
||||
let llfnty = fn_ty.llvm_type(ccx);
|
||||
|
||||
let prefix = match dg {
|
||||
DropGlueKind::Ty(_) => "drop",
|
||||
DropGlueKind::TyContents(_) => "drop_contents",
|
||||
};
|
||||
|
||||
let symbol =
|
||||
symbol_names::exported_name_from_type_and_prefix(ccx.shared(), t, prefix);
|
||||
debug!(" symbol: {}", symbol);
|
||||
assert!(declare::get_defined_value(ccx, &symbol).is_none());
|
||||
let llfn = declare::declare_cfn(ccx, &symbol, llfnty);
|
||||
attributes::set_frame_pointer_elimination(ccx, llfn);
|
||||
llvm::SetLinkage(llfn, linkage);
|
||||
ccx.drop_glues().borrow_mut().insert(dg, (llfn, fn_ty));
|
||||
}
|
||||
|
||||
pub fn requests_inline(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> bool {
|
||||
match *self {
|
||||
@ -216,8 +294,7 @@ impl<'a, 'tcx> TransItem<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_string(&self, scx: &SharedCrateContext<'a, 'tcx>) -> String {
|
||||
let tcx = scx.tcx();
|
||||
pub fn to_string(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> String {
|
||||
let hir_map = &tcx.map;
|
||||
|
||||
return match *self {
|
||||
@ -235,7 +312,8 @@ impl<'a, 'tcx> TransItem<'tcx> {
|
||||
},
|
||||
TransItem::Static(node_id) => {
|
||||
let def_id = hir_map.local_def_id(node_id);
|
||||
let instance = Instance::mono(scx, def_id);
|
||||
let instance = Instance::new(def_id,
|
||||
tcx.mk_substs(subst::Substs::empty()));
|
||||
to_string_internal(tcx, "static ", instance)
|
||||
},
|
||||
};
|
||||
@ -254,7 +332,11 @@ impl<'a, 'tcx> TransItem<'tcx> {
|
||||
pub fn to_raw_string(&self) -> String {
|
||||
match *self {
|
||||
TransItem::DropGlue(dg) => {
|
||||
format!("DropGlue({})", dg.ty() as *const _ as usize)
|
||||
let prefix = match dg {
|
||||
DropGlueKind::Ty(_) => "Ty",
|
||||
DropGlueKind::TyContents(_) => "TyContents",
|
||||
};
|
||||
format!("DropGlue({}: {})", prefix, dg.ty() as *const _ as usize)
|
||||
}
|
||||
TransItem::Fn(instance) => {
|
||||
format!("Fn({:?}, {})",
|
||||
|
Loading…
Reference in New Issue
Block a user