]> git.lizzy.rs Git - rust.git/blob - src/librustc/middle/trans/context.rs
2879e4babbceb91249ee54fcb83c1612f54e3eec
[rust.git] / src / librustc / middle / trans / context.rs
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.
4 //
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.
10
11
12 use back::{upcall};
13 use driver::session;
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;
19 use middle::resolve;
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::ty;
26
27 use middle::trans::type_::Type;
28
29 use std::hash;
30 use std::hashmap::{HashMap, HashSet};
31 use std::str;
32 use std::local_data;
33 use syntax::ast;
34
35 use middle::trans::common::{mono_id,ExternMap,tydesc_info,BuilderRef_res,Stats};
36
37 use middle::trans::base::{decl_crate_map};
38
39 pub struct CrateContext {
40      sess: session::Session,
41      llmod: ModuleRef,
42      llcx: ContextRef,
43      td: TargetData,
44      tn: TypeNames,
45      externs: ExternMap,
46      intrinsics: HashMap<&'static str, ValueRef>,
47      item_vals: HashMap<ast::node_id, ValueRef>,
48      exp_map2: resolve::ExportMap2,
49      reachable: @mut HashSet<ast::node_id>,
50      item_symbols: HashMap<ast::node_id, ~str>,
51      link_meta: LinkMeta,
52      enum_sizes: HashMap<ty::t, uint>,
53      discrims: HashMap<ast::def_id, ValueRef>,
54      discrim_symbols: HashMap<ast::node_id, @str>,
55      tydescs: HashMap<ty::t, @mut tydesc_info>,
56      // Set when running emit_tydescs to enforce that no more tydescs are
57      // created.
58      finished_tydescs: bool,
59      // Track mapping of external ids to local items imported for inlining
60      external: HashMap<ast::def_id, Option<ast::node_id>>,
61      // Cache instances of monomorphized functions
62      monomorphized: HashMap<mono_id, ValueRef>,
63      monomorphizing: HashMap<ast::def_id, uint>,
64      // Cache computed type parameter uses (see type_use.rs)
65      type_use_cache: HashMap<ast::def_id, @~[type_use::type_uses]>,
66      // Cache generated vtables
67      vtables: HashMap<mono_id, ValueRef>,
68      // Cache of constant strings,
69      const_cstr_cache: HashMap<@str, ValueRef>,
70
71      // Reverse-direction for const ptrs cast from globals.
72      // Key is an int, cast from a ValueRef holding a *T,
73      // Val is a ValueRef holding a *[T].
74      //
75      // Needed because LLVM loses pointer->pointee association
76      // when we ptrcast, and we have to ptrcast during translation
77      // of a [T] const because we form a slice, a [*T,int] pair, not
78      // a pointer to an LLVM array type.
79      const_globals: HashMap<int, ValueRef>,
80
81      // Cache of emitted const values
82      const_values: HashMap<ast::node_id, ValueRef>,
83
84      // Cache of external const values
85      extern_const_values: HashMap<ast::def_id, ValueRef>,
86
87      impl_method_cache: HashMap<(ast::def_id, ast::ident), ast::def_id>,
88
89      module_data: HashMap<~str, ValueRef>,
90      lltypes: HashMap<ty::t, Type>,
91      llsizingtypes: HashMap<ty::t, Type>,
92      adt_reprs: HashMap<ty::t, @adt::Repr>,
93      symbol_hasher: hash::State,
94      type_hashcodes: HashMap<ty::t, @str>,
95      type_short_names: HashMap<ty::t, ~str>,
96      all_llvm_symbols: HashSet<@str>,
97      tcx: ty::ctxt,
98      maps: astencode::Maps,
99      stats: @mut Stats,
100      upcalls: @upcall::Upcalls,
101      tydesc_type: Type,
102      int_type: Type,
103      float_type: Type,
104      opaque_vec_type: Type,
105      builder: BuilderRef_res,
106      crate_map: ValueRef,
107      // Set when at least one function uses GC. Needed so that
108      // decl_gc_metadata knows whether to link to the module metadata, which
109      // is not emitted by LLVM's GC pass when no functions use GC.
110      uses_gc: bool,
111      dbg_cx: Option<debuginfo::DebugContext>,
112      do_not_commit_warning_issued: bool
113 }
114
115 impl CrateContext {
116     pub fn new(sess: session::Session,
117                name: &str,
118                tcx: ty::ctxt,
119                emap2: resolve::ExportMap2,
120                maps: astencode::Maps,
121                symbol_hasher: hash::State,
122                link_meta: LinkMeta,
123                reachable: @mut HashSet<ast::node_id>)
124                -> CrateContext {
125         unsafe {
126             let llcx = llvm::LLVMContextCreate();
127             set_task_llcx(llcx);
128             let llmod = str::as_c_str(name, |buf| {
129                 llvm::LLVMModuleCreateWithNameInContext(buf, llcx)
130             });
131             let data_layout: &str = sess.targ_cfg.target_strs.data_layout;
132             let targ_triple: &str = sess.targ_cfg.target_strs.target_triple;
133             str::as_c_str(data_layout, |buf| llvm::LLVMSetDataLayout(llmod, buf));
134             str::as_c_str(targ_triple, |buf| llvm::LLVMSetTarget(llmod, buf));
135             let targ_cfg = sess.targ_cfg;
136
137             let td = mk_target_data(sess.targ_cfg.target_strs.data_layout);
138             let mut tn = TypeNames::new();
139
140             let mut intrinsics = base::declare_intrinsics(llmod);
141             if sess.opts.extra_debuginfo {
142                 base::declare_dbg_intrinsics(llmod, &mut intrinsics);
143             }
144             let int_type = Type::int(targ_cfg.arch);
145             let float_type = Type::float(targ_cfg.arch);
146             let tydesc_type = Type::tydesc(targ_cfg.arch);
147             let opaque_vec_type = Type::opaque_vec(targ_cfg.arch);
148
149             let mut str_slice_ty = Type::named_struct("str_slice");
150             str_slice_ty.set_struct_body([Type::i8p(), int_type], false);
151
152             tn.associate_type("tydesc", &tydesc_type);
153             tn.associate_type("str_slice", &str_slice_ty);
154
155             let crate_map = decl_crate_map(sess, link_meta, llmod);
156             let dbg_cx = if sess.opts.debuginfo {
157                 Some(debuginfo::DebugContext::new(llmod, name.to_owned()))
158             } else {
159                 None
160             };
161
162             if sess.count_llvm_insns() {
163                 base::init_insn_ctxt()
164             }
165
166             CrateContext {
167                   sess: sess,
168                   llmod: llmod,
169                   llcx: llcx,
170                   td: td,
171                   tn: tn,
172                   externs: HashMap::new(),
173                   intrinsics: intrinsics,
174                   item_vals: HashMap::new(),
175                   exp_map2: emap2,
176                   reachable: reachable,
177                   item_symbols: HashMap::new(),
178                   link_meta: link_meta,
179                   enum_sizes: HashMap::new(),
180                   discrims: HashMap::new(),
181                   discrim_symbols: HashMap::new(),
182                   tydescs: HashMap::new(),
183                   finished_tydescs: false,
184                   external: HashMap::new(),
185                   monomorphized: HashMap::new(),
186                   monomorphizing: HashMap::new(),
187                   type_use_cache: HashMap::new(),
188                   vtables: HashMap::new(),
189                   const_cstr_cache: HashMap::new(),
190                   const_globals: HashMap::new(),
191                   const_values: HashMap::new(),
192                   extern_const_values: HashMap::new(),
193                   impl_method_cache: HashMap::new(),
194                   module_data: HashMap::new(),
195                   lltypes: HashMap::new(),
196                   llsizingtypes: HashMap::new(),
197                   adt_reprs: HashMap::new(),
198                   symbol_hasher: symbol_hasher,
199                   type_hashcodes: HashMap::new(),
200                   type_short_names: HashMap::new(),
201                   all_llvm_symbols: HashSet::new(),
202                   tcx: tcx,
203                   maps: maps,
204                   stats: @mut Stats {
205                     n_static_tydescs: 0u,
206                     n_glues_created: 0u,
207                     n_null_glues: 0u,
208                     n_real_glues: 0u,
209                     n_fns: 0u,
210                     n_monos: 0u,
211                     n_inlines: 0u,
212                     n_closures: 0u,
213                     n_llvm_insns: 0u,
214                     llvm_insn_ctxt: ~[],
215                     llvm_insns: HashMap::new(),
216                     fn_stats: ~[]
217                   },
218                   upcalls: upcall::declare_upcalls(targ_cfg, llmod),
219                   tydesc_type: tydesc_type,
220                   int_type: int_type,
221                   float_type: float_type,
222                   opaque_vec_type: opaque_vec_type,
223                   builder: BuilderRef_res(llvm::LLVMCreateBuilderInContext(llcx)),
224                   crate_map: crate_map,
225                   uses_gc: false,
226                   dbg_cx: dbg_cx,
227                   do_not_commit_warning_issued: false
228             }
229         }
230     }
231
232     pub fn builder(@mut self) -> Builder {
233         Builder::new(self)
234     }
235 }
236
237 #[unsafe_destructor]
238 impl Drop for CrateContext {
239     fn drop(&self) {
240         unset_task_llcx();
241     }
242 }
243
244 static task_local_llcx_key: local_data::Key<@ContextRef> = &local_data::Key;
245
246 pub fn task_llcx() -> ContextRef {
247     let opt = local_data::get(task_local_llcx_key, |k| k.map(|&k| *k));
248     *opt.expect("task-local LLVMContextRef wasn't ever set!")
249 }
250
251 fn set_task_llcx(c: ContextRef) {
252     local_data::set(task_local_llcx_key, @c);
253 }
254
255 fn unset_task_llcx() {
256     local_data::pop(task_local_llcx_key);
257 }