split CrateContext into shared and local pieces
Break up `CrateContext` into `SharedCrateContext` and `LocalCrateContext`. The local piece corresponds to a single compilation unit, and contains all LLVM-related components. (LLVM data structures are tied to a specific `LLVMContext`, and we will need separate `LLVMContext`s to safely run multithreaded optimization.) The shared piece contains data structures that need to be shared across all compilation units, such as the `ty::ctxt` and some tables related to crate metadata.
This commit is contained in:
parent
cf35cb365a
commit
0ab27b1d5b
|
@ -405,6 +405,7 @@ pub mod write {
|
|||
|
||||
llvm::LLVMRustDisposeTargetMachine(tm);
|
||||
llvm::LLVMDisposeModule(trans.metadata_module);
|
||||
llvm::LLVMContextDispose(trans.metadata_context);
|
||||
llvm::LLVMDisposeModule(llmod);
|
||||
llvm::LLVMContextDispose(llcx);
|
||||
if sess.time_llvm_passes() { llvm::LLVMRustPrintPassTimings(); }
|
||||
|
|
|
@ -444,6 +444,7 @@ pub fn phase_save_analysis(sess: &Session,
|
|||
pub struct CrateTranslation {
|
||||
pub context: ContextRef,
|
||||
pub module: ModuleRef,
|
||||
pub metadata_context: ContextRef,
|
||||
pub metadata_module: ModuleRef,
|
||||
pub link: LinkMeta,
|
||||
pub metadata: Vec<u8>,
|
||||
|
|
|
@ -56,6 +56,7 @@ use middle::trans::common::{tydesc_info, type_is_immediate};
|
|||
use middle::trans::common::{type_is_zero_size, val_ty};
|
||||
use middle::trans::common;
|
||||
use middle::trans::consts;
|
||||
use middle::trans::context::SharedCrateContext;
|
||||
use middle::trans::controlflow;
|
||||
use middle::trans::datum;
|
||||
use middle::trans::debuginfo;
|
||||
|
@ -136,7 +137,7 @@ pub fn push_ctxt(s: &'static str) -> _InsnCtxt {
|
|||
}
|
||||
|
||||
pub struct StatRecorder<'a> {
|
||||
ccx: &'a CrateContext,
|
||||
ccx: &'a CrateContext<'a>,
|
||||
name: Option<String>,
|
||||
start: u64,
|
||||
istart: uint,
|
||||
|
@ -2114,7 +2115,7 @@ fn enum_variant_size_lint(ccx: &CrateContext, enum_def: &ast::EnumDef, sp: Span,
|
|||
}
|
||||
|
||||
pub struct TransItemVisitor<'a> {
|
||||
pub ccx: &'a CrateContext,
|
||||
pub ccx: &'a CrateContext<'a>,
|
||||
}
|
||||
|
||||
impl<'a> Visitor<()> for TransItemVisitor<'a> {
|
||||
|
@ -2895,19 +2896,18 @@ pub fn trans_crate(krate: ast::Crate,
|
|||
|
||||
let link_meta = link::build_link_meta(&tcx.sess, &krate, name);
|
||||
|
||||
// Append ".rs" to crate name as LLVM module identifier.
|
||||
//
|
||||
// LLVM code generator emits a ".file filename" directive
|
||||
// for ELF backends. Value of the "filename" is set as the
|
||||
// LLVM module identifier. Due to a LLVM MC bug[1], LLVM
|
||||
// crashes if the module identifier is same as other symbols
|
||||
// such as a function name in the module.
|
||||
// 1. http://llvm.org/bugs/show_bug.cgi?id=11479
|
||||
let mut llmod_id = link_meta.crate_name.clone();
|
||||
llmod_id.push_str(".rs");
|
||||
// Multiple compilation units won't be supported until a later commit.
|
||||
let codegen_units = 1;
|
||||
let shared_ccx = SharedCrateContext::new(link_meta.crate_name.as_slice(),
|
||||
codegen_units,
|
||||
tcx,
|
||||
exp_map2,
|
||||
Sha256::new(),
|
||||
link_meta.clone(),
|
||||
reachable);
|
||||
|
||||
let ccx = CrateContext::new(llmod_id.as_slice(), tcx, exp_map2,
|
||||
Sha256::new(), link_meta, reachable);
|
||||
let metadata = {
|
||||
let ccx = shared_ccx.get_ccx(0);
|
||||
|
||||
// First, verify intrinsics.
|
||||
intrinsic::check_intrinsics(&ccx);
|
||||
|
@ -2924,23 +2924,26 @@ pub fn trans_crate(krate: ast::Crate,
|
|||
}
|
||||
|
||||
// Translate the metadata.
|
||||
let metadata = write_metadata(&ccx, &krate);
|
||||
if ccx.sess().trans_stats() {
|
||||
println!("--- trans stats ---");
|
||||
println!("n_static_tydescs: {}", ccx.stats().n_static_tydescs.get());
|
||||
println!("n_glues_created: {}", ccx.stats().n_glues_created.get());
|
||||
println!("n_null_glues: {}", ccx.stats().n_null_glues.get());
|
||||
println!("n_real_glues: {}", ccx.stats().n_real_glues.get());
|
||||
write_metadata(&ccx, &krate)
|
||||
};
|
||||
|
||||
println!("n_fns: {}", ccx.stats().n_fns.get());
|
||||
println!("n_monos: {}", ccx.stats().n_monos.get());
|
||||
println!("n_inlines: {}", ccx.stats().n_inlines.get());
|
||||
println!("n_closures: {}", ccx.stats().n_closures.get());
|
||||
if shared_ccx.sess().trans_stats() {
|
||||
let stats = shared_ccx.stats();
|
||||
println!("--- trans stats ---");
|
||||
println!("n_static_tydescs: {}", stats.n_static_tydescs.get());
|
||||
println!("n_glues_created: {}", stats.n_glues_created.get());
|
||||
println!("n_null_glues: {}", stats.n_null_glues.get());
|
||||
println!("n_real_glues: {}", stats.n_real_glues.get());
|
||||
|
||||
println!("n_fns: {}", stats.n_fns.get());
|
||||
println!("n_monos: {}", stats.n_monos.get());
|
||||
println!("n_inlines: {}", stats.n_inlines.get());
|
||||
println!("n_closures: {}", stats.n_closures.get());
|
||||
println!("fn stats:");
|
||||
ccx.stats().fn_stats.borrow_mut().sort_by(|&(_, _, insns_a), &(_, _, insns_b)| {
|
||||
stats.fn_stats.borrow_mut().sort_by(|&(_, _, insns_a), &(_, _, insns_b)| {
|
||||
insns_b.cmp(&insns_a)
|
||||
});
|
||||
for tuple in ccx.stats().fn_stats.borrow().iter() {
|
||||
for tuple in stats.fn_stats.borrow().iter() {
|
||||
match *tuple {
|
||||
(ref name, ms, insns) => {
|
||||
println!("{} insns, {} ms, {}", insns, ms, *name);
|
||||
|
@ -2948,27 +2951,26 @@ pub fn trans_crate(krate: ast::Crate,
|
|||
}
|
||||
}
|
||||
}
|
||||
if ccx.sess().count_llvm_insns() {
|
||||
for (k, v) in ccx.stats().llvm_insns.borrow().iter() {
|
||||
if shared_ccx.sess().count_llvm_insns() {
|
||||
for (k, v) in shared_ccx.stats().llvm_insns.borrow().iter() {
|
||||
println!("{:7u} {}", *v, *k);
|
||||
}
|
||||
}
|
||||
|
||||
let llcx = ccx.llcx();
|
||||
let link_meta = ccx.link_meta().clone();
|
||||
let llmod = ccx.llmod();
|
||||
let llcx = shared_ccx.get_ccx(0).llcx();
|
||||
let llmod = shared_ccx.get_ccx(0).llmod();
|
||||
|
||||
let mut reachable: Vec<String> = ccx.reachable().iter().filter_map(|id| {
|
||||
ccx.item_symbols().borrow().find(id).map(|s| s.to_string())
|
||||
let mut reachable: Vec<String> = shared_ccx.reachable().iter().filter_map(|id| {
|
||||
shared_ccx.item_symbols().borrow().find(id).map(|s| s.to_string())
|
||||
}).collect();
|
||||
|
||||
// For the purposes of LTO, we add to the reachable set all of the upstream
|
||||
// reachable extern fns. These functions are all part of the public ABI of
|
||||
// the final product, so LTO needs to preserve them.
|
||||
ccx.sess().cstore.iter_crate_data(|cnum, _| {
|
||||
let syms = csearch::get_reachable_extern_fns(&ccx.sess().cstore, cnum);
|
||||
shared_ccx.sess().cstore.iter_crate_data(|cnum, _| {
|
||||
let syms = csearch::get_reachable_extern_fns(&shared_ccx.sess().cstore, cnum);
|
||||
reachable.extend(syms.move_iter().map(|did| {
|
||||
csearch::get_symbol(&ccx.sess().cstore, did)
|
||||
csearch::get_symbol(&shared_ccx.sess().cstore, did)
|
||||
}));
|
||||
});
|
||||
|
||||
|
@ -2986,15 +2988,17 @@ pub fn trans_crate(krate: ast::Crate,
|
|||
// referenced from rt/rust_try.ll
|
||||
reachable.push("rust_eh_personality_catch".to_string());
|
||||
|
||||
let metadata_module = ccx.metadata_llmod();
|
||||
let formats = ccx.tcx().dependency_formats.borrow().clone();
|
||||
let metadata_module = shared_ccx.metadata_llmod();
|
||||
let metadata_context = shared_ccx.metadata_llcx();
|
||||
let formats = shared_ccx.tcx().dependency_formats.borrow().clone();
|
||||
let no_builtins = attr::contains_name(krate.attrs.as_slice(), "no_builtins");
|
||||
|
||||
(ccx.take_tcx(), CrateTranslation {
|
||||
(shared_ccx.take_tcx(), CrateTranslation {
|
||||
context: llcx,
|
||||
module: llmod,
|
||||
link: link_meta,
|
||||
metadata_module: metadata_module,
|
||||
metadata_context: metadata_context,
|
||||
metadata: metadata,
|
||||
reachable: reachable,
|
||||
crate_formats: formats,
|
||||
|
|
|
@ -25,7 +25,7 @@ use syntax::codemap::Span;
|
|||
|
||||
pub struct Builder<'a> {
|
||||
pub llbuilder: BuilderRef,
|
||||
pub ccx: &'a CrateContext,
|
||||
pub ccx: &'a CrateContext<'a>,
|
||||
}
|
||||
|
||||
// This is a really awful way to get a zero-length c-string, but better (and a
|
||||
|
|
|
@ -297,7 +297,7 @@ pub struct FunctionContext<'a> {
|
|||
pub block_arena: &'a TypedArena<Block<'a>>,
|
||||
|
||||
// This function's enclosing crate context.
|
||||
pub ccx: &'a CrateContext,
|
||||
pub ccx: &'a CrateContext<'a>,
|
||||
|
||||
// Used and maintained by the debuginfo module.
|
||||
pub debug_context: debuginfo::FunctionDebugContext,
|
||||
|
@ -449,7 +449,7 @@ impl<'a> Block<'a> {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn ccx(&self) -> &'a CrateContext { self.fcx.ccx }
|
||||
pub fn ccx(&self) -> &'a CrateContext<'a> { self.fcx.ccx }
|
||||
pub fn tcx(&self) -> &'a ty::ctxt {
|
||||
self.fcx.ccx.tcx()
|
||||
}
|
||||
|
|
|
@ -51,18 +51,40 @@ pub struct Stats {
|
|||
pub fn_stats: RefCell<Vec<(String, uint, uint)> >,
|
||||
}
|
||||
|
||||
pub struct CrateContext {
|
||||
llmod: ModuleRef,
|
||||
llcx: ContextRef,
|
||||
/// The shared portion of a `CrateContext`. There is one `SharedCrateContext`
|
||||
/// per crate. The data here is shared between all compilation units of the
|
||||
/// crate, so it must not contain references to any LLVM data structures
|
||||
/// (aside from metadata-related ones).
|
||||
pub struct SharedCrateContext {
|
||||
local_ccxs: Vec<LocalCrateContext>,
|
||||
|
||||
metadata_llmod: ModuleRef,
|
||||
td: TargetData,
|
||||
tn: TypeNames,
|
||||
externs: RefCell<ExternMap>,
|
||||
item_vals: RefCell<NodeMap<ValueRef>>,
|
||||
metadata_llcx: ContextRef,
|
||||
|
||||
exp_map2: resolve::ExportMap2,
|
||||
reachable: NodeSet,
|
||||
item_symbols: RefCell<NodeMap<String>>,
|
||||
link_meta: LinkMeta,
|
||||
/// A set of static items which cannot be inlined into other crates. This
|
||||
/// will prevent in IIItem() structures from being encoded into the metadata
|
||||
/// that is generated
|
||||
non_inlineable_statics: RefCell<NodeSet>,
|
||||
symbol_hasher: RefCell<Sha256>,
|
||||
tcx: ty::ctxt,
|
||||
stats: Stats,
|
||||
}
|
||||
|
||||
/// The local portion of a `CrateContext`. There is one `LocalCrateContext`
|
||||
/// per compilation unit. Each one has its own LLVM `ContextRef` so that
|
||||
/// several compilation units may be optimized in parallel. All other LLVM
|
||||
/// data structures in the `LocalCrateContext` are tied to that `ContextRef`.
|
||||
pub struct LocalCrateContext {
|
||||
llmod: ModuleRef,
|
||||
llcx: ContextRef,
|
||||
td: TargetData,
|
||||
tn: TypeNames,
|
||||
externs: RefCell<ExternMap>,
|
||||
item_vals: RefCell<NodeMap<ValueRef>>,
|
||||
drop_glues: RefCell<HashMap<ty::t, ValueRef>>,
|
||||
tydescs: RefCell<HashMap<ty::t, Rc<tydesc_info>>>,
|
||||
/// Set when running emit_tydescs to enforce that no more tydescs are
|
||||
|
@ -73,10 +95,6 @@ pub struct CrateContext {
|
|||
/// Backwards version of the `external` map (inlined items to where they
|
||||
/// came from)
|
||||
external_srcs: RefCell<NodeMap<ast::DefId>>,
|
||||
/// A set of static items which cannot be inlined into other crates. This
|
||||
/// will prevent in IIItem() structures from being encoded into the metadata
|
||||
/// that is generated
|
||||
non_inlineable_statics: RefCell<NodeSet>,
|
||||
/// Cache instances of monomorphized functions
|
||||
monomorphized: RefCell<HashMap<MonoId, ValueRef>>,
|
||||
monomorphizing: RefCell<DefIdMap<uint>>,
|
||||
|
@ -109,11 +127,8 @@ pub struct CrateContext {
|
|||
lltypes: RefCell<HashMap<ty::t, Type>>,
|
||||
llsizingtypes: RefCell<HashMap<ty::t, Type>>,
|
||||
adt_reprs: RefCell<HashMap<ty::t, Rc<adt::Repr>>>,
|
||||
symbol_hasher: RefCell<Sha256>,
|
||||
type_hashcodes: RefCell<HashMap<ty::t, String>>,
|
||||
all_llvm_symbols: RefCell<HashSet<String>>,
|
||||
tcx: ty::ctxt,
|
||||
stats: Stats,
|
||||
int_type: Type,
|
||||
opaque_vec_type: Type,
|
||||
builder: BuilderRef_res,
|
||||
|
@ -128,86 +143,56 @@ pub struct CrateContext {
|
|||
intrinsics: RefCell<HashMap<&'static str, ValueRef>>,
|
||||
}
|
||||
|
||||
impl CrateContext {
|
||||
pub fn new(name: &str,
|
||||
tcx: ty::ctxt,
|
||||
emap2: resolve::ExportMap2,
|
||||
symbol_hasher: Sha256,
|
||||
link_meta: LinkMeta,
|
||||
reachable: NodeSet)
|
||||
-> CrateContext {
|
||||
unsafe {
|
||||
pub struct CrateContext<'a> {
|
||||
shared: &'a SharedCrateContext,
|
||||
local: &'a LocalCrateContext,
|
||||
}
|
||||
|
||||
unsafe fn create_context_and_module(sess: &Session, mod_name: &str) -> (ContextRef, ModuleRef) {
|
||||
let llcx = llvm::LLVMContextCreate();
|
||||
let llmod = name.with_c_str(|buf| {
|
||||
let llmod = mod_name.with_c_str(|buf| {
|
||||
llvm::LLVMModuleCreateWithNameInContext(buf, llcx)
|
||||
});
|
||||
let metadata_llmod = format!("{}_metadata", name).with_c_str(|buf| {
|
||||
llvm::LLVMModuleCreateWithNameInContext(buf, llcx)
|
||||
});
|
||||
tcx.sess
|
||||
.targ_cfg
|
||||
sess.targ_cfg
|
||||
.target_strs
|
||||
.data_layout
|
||||
.as_slice()
|
||||
.with_c_str(|buf| {
|
||||
llvm::LLVMSetDataLayout(llmod, buf);
|
||||
llvm::LLVMSetDataLayout(metadata_llmod, buf);
|
||||
});
|
||||
tcx.sess
|
||||
.targ_cfg
|
||||
sess.targ_cfg
|
||||
.target_strs
|
||||
.target_triple
|
||||
.as_slice()
|
||||
.with_c_str(|buf| {
|
||||
llvm::LLVMRustSetNormalizedTarget(llmod, buf);
|
||||
llvm::LLVMRustSetNormalizedTarget(metadata_llmod, buf);
|
||||
});
|
||||
(llcx, llmod)
|
||||
}
|
||||
|
||||
let td = mk_target_data(tcx.sess
|
||||
.targ_cfg
|
||||
.target_strs
|
||||
.data_layout
|
||||
.as_slice());
|
||||
|
||||
let dbg_cx = if tcx.sess.opts.debuginfo != NoDebugInfo {
|
||||
Some(debuginfo::CrateDebugContext::new(llmod))
|
||||
} else {
|
||||
None
|
||||
impl SharedCrateContext {
|
||||
pub fn new(crate_name: &str,
|
||||
local_count: uint,
|
||||
tcx: ty::ctxt,
|
||||
emap2: resolve::ExportMap2,
|
||||
symbol_hasher: Sha256,
|
||||
link_meta: LinkMeta,
|
||||
reachable: NodeSet)
|
||||
-> SharedCrateContext {
|
||||
let (metadata_llcx, metadata_llmod) = unsafe {
|
||||
create_context_and_module(&tcx.sess, "metadata")
|
||||
};
|
||||
|
||||
let mut ccx = CrateContext {
|
||||
llmod: llmod,
|
||||
llcx: llcx,
|
||||
let mut shared_ccx = SharedCrateContext {
|
||||
local_ccxs: Vec::with_capacity(local_count),
|
||||
metadata_llmod: metadata_llmod,
|
||||
td: td,
|
||||
tn: TypeNames::new(),
|
||||
externs: RefCell::new(HashMap::new()),
|
||||
item_vals: RefCell::new(NodeMap::new()),
|
||||
metadata_llcx: metadata_llcx,
|
||||
exp_map2: emap2,
|
||||
reachable: reachable,
|
||||
item_symbols: RefCell::new(NodeMap::new()),
|
||||
link_meta: link_meta,
|
||||
drop_glues: RefCell::new(HashMap::new()),
|
||||
tydescs: RefCell::new(HashMap::new()),
|
||||
finished_tydescs: Cell::new(false),
|
||||
external: RefCell::new(DefIdMap::new()),
|
||||
external_srcs: RefCell::new(NodeMap::new()),
|
||||
non_inlineable_statics: RefCell::new(NodeSet::new()),
|
||||
monomorphized: RefCell::new(HashMap::new()),
|
||||
monomorphizing: RefCell::new(DefIdMap::new()),
|
||||
vtables: RefCell::new(HashMap::new()),
|
||||
const_cstr_cache: RefCell::new(HashMap::new()),
|
||||
const_globals: RefCell::new(HashMap::new()),
|
||||
const_values: RefCell::new(NodeMap::new()),
|
||||
extern_const_values: RefCell::new(DefIdMap::new()),
|
||||
impl_method_cache: RefCell::new(HashMap::new()),
|
||||
closure_bare_wrapper_cache: RefCell::new(HashMap::new()),
|
||||
lltypes: RefCell::new(HashMap::new()),
|
||||
llsizingtypes: RefCell::new(HashMap::new()),
|
||||
adt_reprs: RefCell::new(HashMap::new()),
|
||||
symbol_hasher: RefCell::new(symbol_hasher),
|
||||
type_hashcodes: RefCell::new(HashMap::new()),
|
||||
all_llvm_symbols: RefCell::new(HashSet::new()),
|
||||
tcx: tcx,
|
||||
stats: Stats {
|
||||
n_static_tydescs: Cell::new(0u),
|
||||
|
@ -222,30 +207,63 @@ impl CrateContext {
|
|||
llvm_insns: RefCell::new(HashMap::new()),
|
||||
fn_stats: RefCell::new(Vec::new()),
|
||||
},
|
||||
int_type: Type::from_ref(ptr::mut_null()),
|
||||
opaque_vec_type: Type::from_ref(ptr::mut_null()),
|
||||
builder: BuilderRef_res(llvm::LLVMCreateBuilderInContext(llcx)),
|
||||
unboxed_closure_vals: RefCell::new(DefIdMap::new()),
|
||||
dbg_cx: dbg_cx,
|
||||
eh_personality: RefCell::new(None),
|
||||
intrinsics: RefCell::new(HashMap::new()),
|
||||
};
|
||||
|
||||
ccx.int_type = Type::int(&ccx);
|
||||
ccx.opaque_vec_type = Type::opaque_vec(&ccx);
|
||||
|
||||
let mut str_slice_ty = Type::named_struct(&ccx, "str_slice");
|
||||
str_slice_ty.set_struct_body([Type::i8p(&ccx), ccx.int_type()], false);
|
||||
ccx.tn().associate_type("str_slice", &str_slice_ty);
|
||||
|
||||
ccx.tn().associate_type("tydesc", &Type::tydesc(&ccx, str_slice_ty));
|
||||
|
||||
if ccx.sess().count_llvm_insns() {
|
||||
base::init_insn_ctxt()
|
||||
for i in range(0, local_count) {
|
||||
// Append ".rs" to crate name as LLVM module identifier.
|
||||
//
|
||||
// LLVM code generator emits a ".file filename" directive
|
||||
// for ELF backends. Value of the "filename" is set as the
|
||||
// LLVM module identifier. Due to a LLVM MC bug[1], LLVM
|
||||
// crashes if the module identifier is same as other symbols
|
||||
// such as a function name in the module.
|
||||
// 1. http://llvm.org/bugs/show_bug.cgi?id=11479
|
||||
let llmod_id = format!("{}.{}.rs", crate_name, i);
|
||||
let local_ccx = LocalCrateContext::new(&shared_ccx, llmod_id.as_slice());
|
||||
shared_ccx.local_ccxs.push(local_ccx);
|
||||
}
|
||||
|
||||
ccx
|
||||
shared_ccx
|
||||
}
|
||||
|
||||
pub fn get_ccx<'a>(&'a self, index: uint) -> CrateContext<'a> {
|
||||
CrateContext {
|
||||
shared: self,
|
||||
local: &self.local_ccxs[index],
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn metadata_llmod(&self) -> ModuleRef {
|
||||
self.metadata_llmod
|
||||
}
|
||||
|
||||
pub fn metadata_llcx(&self) -> ContextRef {
|
||||
self.metadata_llcx
|
||||
}
|
||||
|
||||
pub fn exp_map2<'a>(&'a self) -> &'a resolve::ExportMap2 {
|
||||
&self.exp_map2
|
||||
}
|
||||
|
||||
pub fn reachable<'a>(&'a self) -> &'a NodeSet {
|
||||
&self.reachable
|
||||
}
|
||||
|
||||
pub fn item_symbols<'a>(&'a self) -> &'a RefCell<NodeMap<String>> {
|
||||
&self.item_symbols
|
||||
}
|
||||
|
||||
pub fn link_meta<'a>(&'a self) -> &'a LinkMeta {
|
||||
&self.link_meta
|
||||
}
|
||||
|
||||
pub fn non_inlineable_statics<'a>(&'a self) -> &'a RefCell<NodeSet> {
|
||||
&self.non_inlineable_statics
|
||||
}
|
||||
|
||||
pub fn symbol_hasher<'a>(&'a self) -> &'a RefCell<Sha256> {
|
||||
&self.symbol_hasher
|
||||
}
|
||||
|
||||
pub fn tcx<'a>(&'a self) -> &'a ty::ctxt {
|
||||
|
@ -260,20 +278,137 @@ impl CrateContext {
|
|||
&self.tcx.sess
|
||||
}
|
||||
|
||||
pub fn stats<'a>(&'a self) -> &'a Stats {
|
||||
&self.stats
|
||||
}
|
||||
}
|
||||
|
||||
impl LocalCrateContext {
|
||||
fn new(shared: &SharedCrateContext,
|
||||
name: &str)
|
||||
-> LocalCrateContext {
|
||||
unsafe {
|
||||
let (llcx, llmod) = create_context_and_module(&shared.tcx.sess, name);
|
||||
|
||||
let td = mk_target_data(shared.tcx
|
||||
.sess
|
||||
.targ_cfg
|
||||
.target_strs
|
||||
.data_layout
|
||||
.as_slice());
|
||||
|
||||
let dbg_cx = if shared.tcx.sess.opts.debuginfo != NoDebugInfo {
|
||||
Some(debuginfo::CrateDebugContext::new(llmod))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let mut local_ccx = LocalCrateContext {
|
||||
llmod: llmod,
|
||||
llcx: llcx,
|
||||
td: td,
|
||||
tn: TypeNames::new(),
|
||||
externs: RefCell::new(HashMap::new()),
|
||||
item_vals: RefCell::new(NodeMap::new()),
|
||||
drop_glues: RefCell::new(HashMap::new()),
|
||||
tydescs: RefCell::new(HashMap::new()),
|
||||
finished_tydescs: Cell::new(false),
|
||||
external: RefCell::new(DefIdMap::new()),
|
||||
external_srcs: RefCell::new(NodeMap::new()),
|
||||
monomorphized: RefCell::new(HashMap::new()),
|
||||
monomorphizing: RefCell::new(DefIdMap::new()),
|
||||
vtables: RefCell::new(HashMap::new()),
|
||||
const_cstr_cache: RefCell::new(HashMap::new()),
|
||||
const_globals: RefCell::new(HashMap::new()),
|
||||
const_values: RefCell::new(NodeMap::new()),
|
||||
extern_const_values: RefCell::new(DefIdMap::new()),
|
||||
impl_method_cache: RefCell::new(HashMap::new()),
|
||||
closure_bare_wrapper_cache: RefCell::new(HashMap::new()),
|
||||
lltypes: RefCell::new(HashMap::new()),
|
||||
llsizingtypes: RefCell::new(HashMap::new()),
|
||||
adt_reprs: RefCell::new(HashMap::new()),
|
||||
type_hashcodes: RefCell::new(HashMap::new()),
|
||||
all_llvm_symbols: RefCell::new(HashSet::new()),
|
||||
int_type: Type::from_ref(ptr::mut_null()),
|
||||
opaque_vec_type: Type::from_ref(ptr::mut_null()),
|
||||
builder: BuilderRef_res(llvm::LLVMCreateBuilderInContext(llcx)),
|
||||
unboxed_closure_vals: RefCell::new(DefIdMap::new()),
|
||||
dbg_cx: dbg_cx,
|
||||
eh_personality: RefCell::new(None),
|
||||
intrinsics: RefCell::new(HashMap::new()),
|
||||
};
|
||||
|
||||
local_ccx.int_type = Type::int(&local_ccx.dummy_ccx(shared));
|
||||
local_ccx.opaque_vec_type = Type::opaque_vec(&local_ccx.dummy_ccx(shared));
|
||||
|
||||
// Done mutating local_ccx directly. (The rest of the
|
||||
// initialization goes through RefCell.)
|
||||
{
|
||||
let ccx = local_ccx.dummy_ccx(shared);
|
||||
|
||||
let mut str_slice_ty = Type::named_struct(&ccx, "str_slice");
|
||||
str_slice_ty.set_struct_body([Type::i8p(&ccx), ccx.int_type()], false);
|
||||
ccx.tn().associate_type("str_slice", &str_slice_ty);
|
||||
|
||||
ccx.tn().associate_type("tydesc", &Type::tydesc(&ccx, str_slice_ty));
|
||||
|
||||
if ccx.sess().count_llvm_insns() {
|
||||
base::init_insn_ctxt()
|
||||
}
|
||||
}
|
||||
|
||||
local_ccx
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a dummy `CrateContext` from `self` and the provided
|
||||
/// `SharedCrateContext`. This is somewhat dangerous because `self` may
|
||||
/// not actually be an element of `shared.local_ccxs`, which can cause some
|
||||
/// operations to `fail` unexpectedly.
|
||||
///
|
||||
/// This is used in the `LocalCrateContext` constructor to allow calling
|
||||
/// functions that expect a complete `CrateContext`, even before the local
|
||||
/// portion is fully initialized and attached to the `SharedCrateContext`.
|
||||
fn dummy_ccx<'a>(&'a self, shared: &'a SharedCrateContext) -> CrateContext<'a> {
|
||||
CrateContext {
|
||||
shared: shared,
|
||||
local: self,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'b> CrateContext<'b> {
|
||||
pub fn shared(&self) -> &'b SharedCrateContext {
|
||||
self.shared
|
||||
}
|
||||
|
||||
pub fn local(&self) -> &'b LocalCrateContext {
|
||||
self.local
|
||||
}
|
||||
|
||||
|
||||
pub fn tcx<'a>(&'a self) -> &'a ty::ctxt {
|
||||
&self.shared.tcx
|
||||
}
|
||||
|
||||
pub fn sess<'a>(&'a self) -> &'a Session {
|
||||
&self.shared.tcx.sess
|
||||
}
|
||||
|
||||
pub fn builder<'a>(&'a self) -> Builder<'a> {
|
||||
Builder::new(self)
|
||||
}
|
||||
|
||||
pub fn raw_builder<'a>(&'a self) -> BuilderRef {
|
||||
self.builder.b
|
||||
self.local.builder.b
|
||||
}
|
||||
|
||||
pub fn tydesc_type(&self) -> Type {
|
||||
self.tn.find_type("tydesc").unwrap()
|
||||
self.local.tn.find_type("tydesc").unwrap()
|
||||
}
|
||||
|
||||
pub fn get_intrinsic(&self, key: & &'static str) -> ValueRef {
|
||||
match self.intrinsics.borrow().find_copy(key) {
|
||||
match self.intrinsics().borrow().find_copy(key) {
|
||||
Some(v) => return v,
|
||||
_ => {}
|
||||
}
|
||||
|
@ -297,160 +432,164 @@ impl CrateContext {
|
|||
|
||||
|
||||
pub fn llmod(&self) -> ModuleRef {
|
||||
self.llmod
|
||||
self.local.llmod
|
||||
}
|
||||
|
||||
pub fn llcx(&self) -> ContextRef {
|
||||
self.llcx
|
||||
self.local.llcx
|
||||
}
|
||||
|
||||
pub fn metadata_llmod(&self) -> ModuleRef {
|
||||
self.metadata_llmod
|
||||
self.shared.metadata_llmod
|
||||
}
|
||||
|
||||
pub fn metadata_llcx(&self) -> ContextRef {
|
||||
self.shared.metadata_llcx
|
||||
}
|
||||
|
||||
pub fn td<'a>(&'a self) -> &'a TargetData {
|
||||
&self.td
|
||||
&self.local.td
|
||||
}
|
||||
|
||||
pub fn tn<'a>(&'a self) -> &'a TypeNames {
|
||||
&self.tn
|
||||
&self.local.tn
|
||||
}
|
||||
|
||||
pub fn externs<'a>(&'a self) -> &'a RefCell<ExternMap> {
|
||||
&self.externs
|
||||
&self.local.externs
|
||||
}
|
||||
|
||||
pub fn item_vals<'a>(&'a self) -> &'a RefCell<NodeMap<ValueRef>> {
|
||||
&self.item_vals
|
||||
&self.local.item_vals
|
||||
}
|
||||
|
||||
pub fn exp_map2<'a>(&'a self) -> &'a resolve::ExportMap2 {
|
||||
&self.exp_map2
|
||||
&self.shared.exp_map2
|
||||
}
|
||||
|
||||
pub fn reachable<'a>(&'a self) -> &'a NodeSet {
|
||||
&self.reachable
|
||||
&self.shared.reachable
|
||||
}
|
||||
|
||||
pub fn item_symbols<'a>(&'a self) -> &'a RefCell<NodeMap<String>> {
|
||||
&self.item_symbols
|
||||
&self.shared.item_symbols
|
||||
}
|
||||
|
||||
pub fn link_meta<'a>(&'a self) -> &'a LinkMeta {
|
||||
&self.link_meta
|
||||
&self.shared.link_meta
|
||||
}
|
||||
|
||||
pub fn drop_glues<'a>(&'a self) -> &'a RefCell<HashMap<ty::t, ValueRef>> {
|
||||
&self.drop_glues
|
||||
&self.local.drop_glues
|
||||
}
|
||||
|
||||
pub fn tydescs<'a>(&'a self) -> &'a RefCell<HashMap<ty::t, Rc<tydesc_info>>> {
|
||||
&self.tydescs
|
||||
&self.local.tydescs
|
||||
}
|
||||
|
||||
pub fn finished_tydescs<'a>(&'a self) -> &'a Cell<bool> {
|
||||
&self.finished_tydescs
|
||||
&self.local.finished_tydescs
|
||||
}
|
||||
|
||||
pub fn external<'a>(&'a self) -> &'a RefCell<DefIdMap<Option<ast::NodeId>>> {
|
||||
&self.external
|
||||
&self.local.external
|
||||
}
|
||||
|
||||
pub fn external_srcs<'a>(&'a self) -> &'a RefCell<NodeMap<ast::DefId>> {
|
||||
&self.external_srcs
|
||||
&self.local.external_srcs
|
||||
}
|
||||
|
||||
pub fn non_inlineable_statics<'a>(&'a self) -> &'a RefCell<NodeSet> {
|
||||
&self.non_inlineable_statics
|
||||
&self.shared.non_inlineable_statics
|
||||
}
|
||||
|
||||
pub fn monomorphized<'a>(&'a self) -> &'a RefCell<HashMap<MonoId, ValueRef>> {
|
||||
&self.monomorphized
|
||||
&self.local.monomorphized
|
||||
}
|
||||
|
||||
pub fn monomorphizing<'a>(&'a self) -> &'a RefCell<DefIdMap<uint>> {
|
||||
&self.monomorphizing
|
||||
&self.local.monomorphizing
|
||||
}
|
||||
|
||||
pub fn vtables<'a>(&'a self) -> &'a RefCell<HashMap<(ty::t, MonoId), ValueRef>> {
|
||||
&self.vtables
|
||||
&self.local.vtables
|
||||
}
|
||||
|
||||
pub fn const_cstr_cache<'a>(&'a self) -> &'a RefCell<HashMap<InternedString, ValueRef>> {
|
||||
&self.const_cstr_cache
|
||||
&self.local.const_cstr_cache
|
||||
}
|
||||
|
||||
pub fn const_globals<'a>(&'a self) -> &'a RefCell<HashMap<int, ValueRef>> {
|
||||
&self.const_globals
|
||||
&self.local.const_globals
|
||||
}
|
||||
|
||||
pub fn const_values<'a>(&'a self) -> &'a RefCell<NodeMap<ValueRef>> {
|
||||
&self.const_values
|
||||
&self.local.const_values
|
||||
}
|
||||
|
||||
pub fn extern_const_values<'a>(&'a self) -> &'a RefCell<DefIdMap<ValueRef>> {
|
||||
&self.extern_const_values
|
||||
&self.local.extern_const_values
|
||||
}
|
||||
|
||||
pub fn impl_method_cache<'a>(&'a self)
|
||||
-> &'a RefCell<HashMap<(ast::DefId, ast::Name), ast::DefId>> {
|
||||
&self.impl_method_cache
|
||||
&self.local.impl_method_cache
|
||||
}
|
||||
|
||||
pub fn closure_bare_wrapper_cache<'a>(&'a self) -> &'a RefCell<HashMap<ValueRef, ValueRef>> {
|
||||
&self.closure_bare_wrapper_cache
|
||||
&self.local.closure_bare_wrapper_cache
|
||||
}
|
||||
|
||||
pub fn lltypes<'a>(&'a self) -> &'a RefCell<HashMap<ty::t, Type>> {
|
||||
&self.lltypes
|
||||
&self.local.lltypes
|
||||
}
|
||||
|
||||
pub fn llsizingtypes<'a>(&'a self) -> &'a RefCell<HashMap<ty::t, Type>> {
|
||||
&self.llsizingtypes
|
||||
&self.local.llsizingtypes
|
||||
}
|
||||
|
||||
pub fn adt_reprs<'a>(&'a self) -> &'a RefCell<HashMap<ty::t, Rc<adt::Repr>>> {
|
||||
&self.adt_reprs
|
||||
&self.local.adt_reprs
|
||||
}
|
||||
|
||||
pub fn symbol_hasher<'a>(&'a self) -> &'a RefCell<Sha256> {
|
||||
&self.symbol_hasher
|
||||
&self.shared.symbol_hasher
|
||||
}
|
||||
|
||||
pub fn type_hashcodes<'a>(&'a self) -> &'a RefCell<HashMap<ty::t, String>> {
|
||||
&self.type_hashcodes
|
||||
&self.local.type_hashcodes
|
||||
}
|
||||
|
||||
pub fn all_llvm_symbols<'a>(&'a self) -> &'a RefCell<HashSet<String>> {
|
||||
&self.all_llvm_symbols
|
||||
&self.local.all_llvm_symbols
|
||||
}
|
||||
|
||||
pub fn stats<'a>(&'a self) -> &'a Stats {
|
||||
&self.stats
|
||||
&self.shared.stats
|
||||
}
|
||||
|
||||
pub fn int_type(&self) -> Type {
|
||||
self.int_type
|
||||
self.local.int_type
|
||||
}
|
||||
|
||||
pub fn opaque_vec_type(&self) -> Type {
|
||||
self.opaque_vec_type
|
||||
self.local.opaque_vec_type
|
||||
}
|
||||
|
||||
pub fn unboxed_closure_vals<'a>(&'a self) -> &'a RefCell<DefIdMap<ValueRef>> {
|
||||
&self.unboxed_closure_vals
|
||||
&self.local.unboxed_closure_vals
|
||||
}
|
||||
|
||||
pub fn dbg_cx<'a>(&'a self) -> &'a Option<debuginfo::CrateDebugContext> {
|
||||
&self.dbg_cx
|
||||
&self.local.dbg_cx
|
||||
}
|
||||
|
||||
pub fn eh_personality<'a>(&'a self) -> &'a RefCell<Option<ValueRef>> {
|
||||
&self.eh_personality
|
||||
&self.local.eh_personality
|
||||
}
|
||||
|
||||
fn intrinsics<'a>(&'a self) -> &'a RefCell<HashMap<&'static str, ValueRef>> {
|
||||
&self.intrinsics
|
||||
&self.local.intrinsics
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue