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.
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::debuginfo;
24 use middle::trans::type_use;
25 use middle::trans::common::{C_i32, C_null};
28 use middle::trans::type_::Type;
30 use std::c_str::ToCStr;
32 use std::hashmap::{HashMap, HashSet};
35 use std::libc::c_uint;
38 use middle::trans::common::{mono_id,ExternMap,tydesc_info,BuilderRef_res,Stats};
40 use middle::trans::base::{decl_crate_map};
42 pub struct CrateContext {
43 sess: session::Session,
49 intrinsics: HashMap<&'static str, ValueRef>,
50 item_vals: HashMap<ast::NodeId, ValueRef>,
51 exp_map2: resolve::ExportMap2,
52 reachable: @mut HashSet<ast::NodeId>,
53 item_symbols: HashMap<ast::NodeId, ~str>,
55 enum_sizes: HashMap<ty::t, uint>,
56 discrims: HashMap<ast::DefId, ValueRef>,
57 discrim_symbols: HashMap<ast::NodeId, @str>,
58 tydescs: HashMap<ty::t, @mut tydesc_info>,
59 // Set when running emit_tydescs to enforce that no more tydescs are
61 finished_tydescs: bool,
62 // Track mapping of external ids to local items imported for inlining
63 external: HashMap<ast::DefId, Option<ast::NodeId>>,
64 // Backwards version of the `external` map (inlined items to where they
66 external_srcs: HashMap<ast::NodeId, ast::DefId>,
67 // A set of static items which cannot be inlined into other crates. This
68 // will pevent in ii_item() structures from being encoded into the metadata
70 non_inlineable_statics: HashSet<ast::NodeId>,
71 // Cache instances of monomorphized functions
72 monomorphized: HashMap<mono_id, ValueRef>,
73 monomorphizing: HashMap<ast::DefId, uint>,
74 // Cache computed type parameter uses (see type_use.rs)
75 type_use_cache: HashMap<ast::DefId, @~[type_use::type_uses]>,
76 // Cache generated vtables
77 vtables: HashMap<(ty::t, mono_id), ValueRef>,
78 // Cache of constant strings,
79 const_cstr_cache: HashMap<@str, ValueRef>,
81 // Reverse-direction for const ptrs cast from globals.
82 // Key is an int, cast from a ValueRef holding a *T,
83 // Val is a ValueRef holding a *[T].
85 // Needed because LLVM loses pointer->pointee association
86 // when we ptrcast, and we have to ptrcast during translation
87 // of a [T] const because we form a slice, a [*T,int] pair, not
88 // a pointer to an LLVM array type.
89 const_globals: HashMap<int, ValueRef>,
91 // Cache of emitted const values
92 const_values: HashMap<ast::NodeId, ValueRef>,
94 // Cache of external const values
95 extern_const_values: HashMap<ast::DefId, ValueRef>,
97 impl_method_cache: HashMap<(ast::DefId, ast::Name), ast::DefId>,
99 module_data: HashMap<~str, ValueRef>,
100 lltypes: HashMap<ty::t, Type>,
101 llsizingtypes: HashMap<ty::t, Type>,
102 adt_reprs: HashMap<ty::t, @adt::Repr>,
103 symbol_hasher: hash::State,
104 type_hashcodes: HashMap<ty::t, @str>,
105 type_short_names: HashMap<ty::t, ~str>,
106 all_llvm_symbols: HashSet<@str>,
108 maps: astencode::Maps,
110 upcalls: @upcall::Upcalls,
114 opaque_vec_type: Type,
115 builder: BuilderRef_res,
117 // Set when at least one function uses GC. Needed so that
118 // decl_gc_metadata knows whether to link to the module metadata, which
119 // is not emitted by LLVM's GC pass when no functions use GC.
121 dbg_cx: Option<debuginfo::CrateDebugContext>,
122 do_not_commit_warning_issued: bool
126 pub fn new(sess: session::Session,
129 emap2: resolve::ExportMap2,
130 maps: astencode::Maps,
131 symbol_hasher: hash::State,
133 reachable: @mut HashSet<ast::NodeId>)
136 let llcx = llvm::LLVMContextCreate();
138 let llmod = do name.with_c_str |buf| {
139 llvm::LLVMModuleCreateWithNameInContext(buf, llcx)
141 let data_layout: &str = sess.targ_cfg.target_strs.data_layout;
142 let targ_triple: &str = sess.targ_cfg.target_strs.target_triple;
143 do data_layout.with_c_str |buf| {
144 llvm::LLVMSetDataLayout(llmod, buf)
146 do targ_triple.with_c_str |buf| {
147 llvm::LLVMRustSetNormalizedTarget(llmod, buf)
149 let targ_cfg = sess.targ_cfg;
151 let td = mk_target_data(sess.targ_cfg.target_strs.data_layout);
152 let mut tn = TypeNames::new();
154 let mut intrinsics = base::declare_intrinsics(llmod);
155 if sess.opts.extra_debuginfo {
156 base::declare_dbg_intrinsics(llmod, &mut intrinsics);
158 let int_type = Type::int(targ_cfg.arch);
159 let float_type = Type::float(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 = decl_crate_map(sess, link_meta, llmod);
170 let dbg_cx = if sess.opts.debuginfo {
171 Some(debuginfo::CrateDebugContext::new(llmod, name.to_owned()))
176 if sess.count_llvm_insns() {
177 base::init_insn_ctxt()
186 externs: HashMap::new(),
187 intrinsics: intrinsics,
188 item_vals: HashMap::new(),
190 reachable: reachable,
191 item_symbols: HashMap::new(),
192 link_meta: link_meta,
193 enum_sizes: HashMap::new(),
194 discrims: HashMap::new(),
195 discrim_symbols: HashMap::new(),
196 tydescs: HashMap::new(),
197 finished_tydescs: false,
198 external: HashMap::new(),
199 external_srcs: HashMap::new(),
200 non_inlineable_statics: HashSet::new(),
201 monomorphized: HashMap::new(),
202 monomorphizing: HashMap::new(),
203 type_use_cache: HashMap::new(),
204 vtables: HashMap::new(),
205 const_cstr_cache: HashMap::new(),
206 const_globals: HashMap::new(),
207 const_values: HashMap::new(),
208 extern_const_values: HashMap::new(),
209 impl_method_cache: HashMap::new(),
210 module_data: HashMap::new(),
211 lltypes: HashMap::new(),
212 llsizingtypes: HashMap::new(),
213 adt_reprs: HashMap::new(),
214 symbol_hasher: symbol_hasher,
215 type_hashcodes: HashMap::new(),
216 type_short_names: HashMap::new(),
217 all_llvm_symbols: HashSet::new(),
221 n_static_tydescs: 0u,
231 llvm_insns: HashMap::new(),
234 upcalls: upcall::declare_upcalls(targ_cfg, llmod),
235 tydesc_type: tydesc_type,
237 float_type: float_type,
238 opaque_vec_type: opaque_vec_type,
239 builder: BuilderRef_res(llvm::LLVMCreateBuilderInContext(llcx)),
240 crate_map: crate_map,
243 do_not_commit_warning_issued: false
248 pub fn builder(@mut self) -> Builder {
252 pub fn const_inbounds_gepi(&self,
254 indices: &[uint]) -> ValueRef {
255 debug!("const_inbounds_gepi: pointer=%s indices=%?",
256 self.tn.val_to_str(pointer), indices);
258 indices.iter().map(|i| C_i32(*i as i32)).collect();
260 llvm::LLVMConstInBoundsGEP(pointer,
262 indices.len() as c_uint)
266 pub fn offsetof_gep(&self,
268 indices: &[uint]) -> ValueRef {
270 * Returns the offset of applying the given GEP indices
271 * to an instance of `llptr_ty`. Similar to `offsetof` in C,
272 * except that `llptr_ty` must be a pointer type.
276 let null = C_null(llptr_ty);
277 llvm::LLVMConstPtrToInt(self.const_inbounds_gepi(null, indices),
278 self.int_type.to_ref())
284 impl Drop for CrateContext {
290 static task_local_llcx_key: local_data::Key<@ContextRef> = &local_data::Key;
292 pub fn task_llcx() -> ContextRef {
293 let opt = local_data::get(task_local_llcx_key, |k| k.map_move(|k| *k));
294 *opt.expect("task-local LLVMContextRef wasn't ever set!")
297 fn set_task_llcx(c: ContextRef) {
298 local_data::set(task_local_llcx_key, @c);
301 fn unset_task_llcx() {
302 local_data::pop(task_local_llcx_key);