1 // Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
13 use driver::session::NoDebugInfo;
14 use lib::llvm::{ContextRef, ModuleRef, ValueRef};
15 use lib::llvm::{llvm, TargetData, TypeNames};
16 use lib::llvm::mk_target_data;
17 use metadata::common::LinkMeta;
18 use middle::astencode;
20 use middle::trans::adt;
21 use middle::trans::base;
22 use middle::trans::builder::Builder;
23 use middle::trans::common::{C_i32, C_null};
24 use middle::trans::common::{mono_id,ExternMap,tydesc_info,BuilderRef_res,Stats};
25 use middle::trans::base::{decl_crate_map};
26 use middle::trans::debuginfo;
27 use middle::trans::type_::Type;
29 use util::sha2::Sha256;
30 use util::nodemap::{NodeMap, NodeSet, DefIdMap};
32 use std::cell::{Cell, RefCell};
33 use std::c_str::ToCStr;
35 use std::libc::c_uint;
36 use collections::{HashMap, HashSet};
38 use syntax::parse::token::InternedString;
40 pub struct CrateContext {
41 sess: session::Session,
44 metadata_llmod: ModuleRef,
47 externs: RefCell<ExternMap>,
48 intrinsics: HashMap<&'static str, ValueRef>,
49 item_vals: RefCell<NodeMap<ValueRef>>,
50 exp_map2: resolve::ExportMap2,
51 reachable: @RefCell<NodeSet>,
52 item_symbols: RefCell<NodeMap<~str>>,
54 drop_glues: RefCell<HashMap<ty::t, ValueRef>>,
55 tydescs: RefCell<HashMap<ty::t, @tydesc_info>>,
56 // Set when running emit_tydescs to enforce that no more tydescs are
58 finished_tydescs: Cell<bool>,
59 // Track mapping of external ids to local items imported for inlining
60 external: RefCell<DefIdMap<Option<ast::NodeId>>>,
61 // Backwards version of the `external` map (inlined items to where they
63 external_srcs: RefCell<NodeMap<ast::DefId>>,
64 // A set of static items which cannot be inlined into other crates. This
65 // will pevent in IIItem() structures from being encoded into the metadata
67 non_inlineable_statics: RefCell<NodeSet>,
68 // Cache instances of monomorphized functions
69 monomorphized: RefCell<HashMap<mono_id, ValueRef>>,
70 monomorphizing: RefCell<DefIdMap<uint>>,
71 // Cache generated vtables
72 vtables: RefCell<HashMap<(ty::t, mono_id), ValueRef>>,
73 // Cache of constant strings,
74 const_cstr_cache: RefCell<HashMap<InternedString, ValueRef>>,
76 // Reverse-direction for const ptrs cast from globals.
77 // Key is an int, cast from a ValueRef holding a *T,
78 // Val is a ValueRef holding a *[T].
80 // Needed because LLVM loses pointer->pointee association
81 // when we ptrcast, and we have to ptrcast during translation
82 // of a [T] const because we form a slice, a [*T,int] pair, not
83 // a pointer to an LLVM array type.
84 const_globals: RefCell<HashMap<int, ValueRef>>,
86 // Cache of emitted const values
87 const_values: RefCell<NodeMap<ValueRef>>,
89 // Cache of external const values
90 extern_const_values: RefCell<DefIdMap<ValueRef>>,
92 impl_method_cache: RefCell<HashMap<(ast::DefId, ast::Name), ast::DefId>>,
94 // Cache of closure wrappers for bare fn's.
95 closure_bare_wrapper_cache: RefCell<HashMap<ValueRef, ValueRef>>,
97 module_data: RefCell<HashMap<~str, ValueRef>>,
98 lltypes: RefCell<HashMap<ty::t, Type>>,
99 llsizingtypes: RefCell<HashMap<ty::t, Type>>,
100 adt_reprs: RefCell<HashMap<ty::t, @adt::Repr>>,
101 symbol_hasher: RefCell<Sha256>,
102 type_hashcodes: RefCell<HashMap<ty::t, ~str>>,
103 all_llvm_symbols: RefCell<HashSet<~str>>,
105 maps: astencode::Maps,
109 opaque_vec_type: Type,
110 builder: BuilderRef_res,
112 crate_map_name: ~str,
113 // Set when at least one function uses GC. Needed so that
114 // decl_gc_metadata knows whether to link to the module metadata, which
115 // is not emitted by LLVM's GC pass when no functions use GC.
117 dbg_cx: Option<debuginfo::CrateDebugContext>,
118 do_not_commit_warning_issued: Cell<bool>,
122 pub fn new(sess: session::Session,
125 emap2: resolve::ExportMap2,
126 maps: astencode::Maps,
127 symbol_hasher: Sha256,
129 reachable: @RefCell<NodeSet>)
132 let llcx = llvm::LLVMContextCreate();
134 let llmod = name.with_c_str(|buf| {
135 llvm::LLVMModuleCreateWithNameInContext(buf, llcx)
137 let metadata_llmod = format!("{}_metadata", name).with_c_str(|buf| {
138 llvm::LLVMModuleCreateWithNameInContext(buf, llcx)
140 let data_layout: &str = sess.targ_cfg.target_strs.data_layout;
141 let targ_triple: &str = sess.targ_cfg.target_strs.target_triple;
142 data_layout.with_c_str(|buf| {
143 llvm::LLVMSetDataLayout(llmod, buf);
144 llvm::LLVMSetDataLayout(metadata_llmod, buf);
146 targ_triple.with_c_str(|buf| {
147 llvm::LLVMRustSetNormalizedTarget(llmod, buf);
148 llvm::LLVMRustSetNormalizedTarget(metadata_llmod, buf);
150 let targ_cfg = sess.targ_cfg;
152 let td = mk_target_data(sess.targ_cfg.target_strs.data_layout);
153 let tn = TypeNames::new();
155 let mut intrinsics = base::declare_intrinsics(llmod);
156 if sess.opts.debuginfo != NoDebugInfo {
157 base::declare_dbg_intrinsics(llmod, &mut intrinsics);
159 let int_type = Type::int(targ_cfg.arch);
160 let tydesc_type = Type::tydesc(targ_cfg.arch);
161 let opaque_vec_type = Type::opaque_vec(targ_cfg.arch);
163 let mut str_slice_ty = Type::named_struct("str_slice");
164 str_slice_ty.set_struct_body([Type::i8p(), int_type], false);
166 tn.associate_type("tydesc", &tydesc_type);
167 tn.associate_type("str_slice", &str_slice_ty);
169 let (crate_map_name, crate_map) = decl_crate_map(sess, link_meta.clone(), llmod);
170 let dbg_cx = if sess.opts.debuginfo != NoDebugInfo {
171 Some(debuginfo::CrateDebugContext::new(llmod))
176 if sess.count_llvm_insns() {
177 base::init_insn_ctxt()
184 metadata_llmod: metadata_llmod,
187 externs: RefCell::new(HashMap::new()),
188 intrinsics: intrinsics,
189 item_vals: RefCell::new(NodeMap::new()),
191 reachable: reachable,
192 item_symbols: RefCell::new(NodeMap::new()),
193 link_meta: link_meta,
194 drop_glues: RefCell::new(HashMap::new()),
195 tydescs: RefCell::new(HashMap::new()),
196 finished_tydescs: Cell::new(false),
197 external: RefCell::new(DefIdMap::new()),
198 external_srcs: RefCell::new(NodeMap::new()),
199 non_inlineable_statics: RefCell::new(NodeSet::new()),
200 monomorphized: RefCell::new(HashMap::new()),
201 monomorphizing: RefCell::new(DefIdMap::new()),
202 vtables: RefCell::new(HashMap::new()),
203 const_cstr_cache: RefCell::new(HashMap::new()),
204 const_globals: RefCell::new(HashMap::new()),
205 const_values: RefCell::new(NodeMap::new()),
206 extern_const_values: RefCell::new(DefIdMap::new()),
207 impl_method_cache: RefCell::new(HashMap::new()),
208 closure_bare_wrapper_cache: RefCell::new(HashMap::new()),
209 module_data: RefCell::new(HashMap::new()),
210 lltypes: RefCell::new(HashMap::new()),
211 llsizingtypes: RefCell::new(HashMap::new()),
212 adt_reprs: RefCell::new(HashMap::new()),
213 symbol_hasher: RefCell::new(symbol_hasher),
214 type_hashcodes: RefCell::new(HashMap::new()),
215 all_llvm_symbols: RefCell::new(HashSet::new()),
219 n_static_tydescs: Cell::new(0u),
220 n_glues_created: Cell::new(0u),
221 n_null_glues: Cell::new(0u),
222 n_real_glues: Cell::new(0u),
223 n_fns: Cell::new(0u),
224 n_monos: Cell::new(0u),
225 n_inlines: Cell::new(0u),
226 n_closures: Cell::new(0u),
227 n_llvm_insns: Cell::new(0u),
228 llvm_insns: RefCell::new(HashMap::new()),
229 fn_stats: RefCell::new(~[]),
231 tydesc_type: tydesc_type,
233 opaque_vec_type: opaque_vec_type,
234 builder: BuilderRef_res(llvm::LLVMCreateBuilderInContext(llcx)),
235 crate_map: crate_map,
236 crate_map_name: crate_map_name,
239 do_not_commit_warning_issued: Cell::new(false),
244 pub fn builder<'a>(&'a self) -> Builder<'a> {
248 pub fn const_inbounds_gepi(&self,
250 indices: &[uint]) -> ValueRef {
251 debug!("const_inbounds_gepi: pointer={} indices={:?}",
252 self.tn.val_to_str(pointer), indices);
254 indices.iter().map(|i| C_i32(*i as i32)).collect();
256 llvm::LLVMConstInBoundsGEP(pointer,
258 indices.len() as c_uint)
262 pub fn offsetof_gep(&self,
264 indices: &[uint]) -> ValueRef {
266 * Returns the offset of applying the given GEP indices
267 * to an instance of `llptr_ty`. Similar to `offsetof` in C,
268 * except that `llptr_ty` must be a pointer type.
272 let null = C_null(llptr_ty);
273 llvm::LLVMConstPtrToInt(self.const_inbounds_gepi(null, indices),
274 self.int_type.to_ref())
280 impl Drop for CrateContext {
286 local_data_key!(task_local_llcx_key: @ContextRef)
288 pub fn task_llcx() -> ContextRef {
289 let opt = local_data::get(task_local_llcx_key, |k| k.map(|k| *k));
290 *opt.expect("task-local LLVMContextRef wasn't ever set!")
293 fn set_task_llcx(c: ContextRef) {
294 local_data::set(task_local_llcx_key, @c);
297 fn unset_task_llcx() {
298 local_data::pop(task_local_llcx_key);