2013-06-13 02:19:50 -05:00
|
|
|
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
|
|
|
|
// file at the top-level directory of this distribution and at
|
|
|
|
// http://rust-lang.org/COPYRIGHT.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
|
|
// option. This file may not be copied, modified, or distributed
|
|
|
|
// except according to those terms.
|
|
|
|
|
2013-06-12 21:02:33 -05:00
|
|
|
|
2013-06-12 21:49:01 -05:00
|
|
|
use back::{upcall};
|
2013-06-12 21:02:33 -05:00
|
|
|
use driver::session;
|
2013-06-16 05:52:44 -05:00
|
|
|
use lib::llvm::{ContextRef, ModuleRef, ValueRef};
|
2013-06-12 21:49:01 -05:00
|
|
|
use lib::llvm::{llvm, TargetData, TypeNames};
|
2013-08-11 20:12:57 -05:00
|
|
|
use lib::llvm::mk_target_data;
|
2013-06-12 21:02:33 -05:00
|
|
|
use metadata::common::LinkMeta;
|
|
|
|
use middle::astencode;
|
|
|
|
use middle::resolve;
|
|
|
|
use middle::trans::adt;
|
|
|
|
use middle::trans::base;
|
2013-07-21 08:33:40 -05:00
|
|
|
use middle::trans::builder::Builder;
|
2013-06-12 21:02:33 -05:00
|
|
|
use middle::trans::debuginfo;
|
|
|
|
use middle::trans::type_use;
|
2013-08-11 12:42:26 -05:00
|
|
|
use middle::trans::common::{C_i32, C_null};
|
2013-06-12 21:02:33 -05:00
|
|
|
use middle::ty;
|
|
|
|
|
2013-06-15 05:16:47 -05:00
|
|
|
use middle::trans::type_::Type;
|
|
|
|
|
2013-08-03 19:13:14 -05:00
|
|
|
use std::c_str::ToCStr;
|
2013-06-28 17:32:26 -05:00
|
|
|
use std::hash;
|
|
|
|
use std::hashmap::{HashMap, HashSet};
|
|
|
|
use std::local_data;
|
2013-08-11 12:42:26 -05:00
|
|
|
use std::vec;
|
|
|
|
use std::libc::c_uint;
|
2013-06-12 21:49:01 -05:00
|
|
|
use syntax::ast;
|
2013-06-12 21:02:33 -05:00
|
|
|
|
2013-06-21 03:28:33 -05:00
|
|
|
use middle::trans::common::{mono_id,ExternMap,tydesc_info,BuilderRef_res,Stats};
|
2013-06-12 21:49:01 -05:00
|
|
|
|
|
|
|
use middle::trans::base::{decl_crate_map};
|
|
|
|
|
2013-06-12 21:02:33 -05:00
|
|
|
pub struct CrateContext {
|
|
|
|
sess: session::Session,
|
|
|
|
llmod: ModuleRef,
|
|
|
|
llcx: ContextRef,
|
|
|
|
td: TargetData,
|
2013-06-14 21:31:52 -05:00
|
|
|
tn: TypeNames,
|
2013-06-12 21:02:33 -05:00
|
|
|
externs: ExternMap,
|
|
|
|
intrinsics: HashMap<&'static str, ValueRef>,
|
2013-07-27 03:25:59 -05:00
|
|
|
item_vals: HashMap<ast::NodeId, ValueRef>,
|
2013-06-12 21:02:33 -05:00
|
|
|
exp_map2: resolve::ExportMap2,
|
2013-07-27 03:25:59 -05:00
|
|
|
reachable: @mut HashSet<ast::NodeId>,
|
|
|
|
item_symbols: HashMap<ast::NodeId, ~str>,
|
2013-06-12 21:02:33 -05:00
|
|
|
link_meta: LinkMeta,
|
2013-06-13 02:19:50 -05:00
|
|
|
enum_sizes: HashMap<ty::t, uint>,
|
|
|
|
discrims: HashMap<ast::def_id, ValueRef>,
|
2013-07-27 03:25:59 -05:00
|
|
|
discrim_symbols: HashMap<ast::NodeId, @str>,
|
2013-06-13 02:19:50 -05:00
|
|
|
tydescs: HashMap<ty::t, @mut tydesc_info>,
|
2013-06-12 21:02:33 -05:00
|
|
|
// Set when running emit_tydescs to enforce that no more tydescs are
|
|
|
|
// created.
|
2013-06-13 02:19:50 -05:00
|
|
|
finished_tydescs: bool,
|
2013-06-12 21:02:33 -05:00
|
|
|
// Track mapping of external ids to local items imported for inlining
|
2013-07-27 03:25:59 -05:00
|
|
|
external: HashMap<ast::def_id, Option<ast::NodeId>>,
|
2013-06-12 21:02:33 -05:00
|
|
|
// Cache instances of monomorphized functions
|
2013-06-13 02:19:50 -05:00
|
|
|
monomorphized: HashMap<mono_id, ValueRef>,
|
|
|
|
monomorphizing: HashMap<ast::def_id, uint>,
|
2013-06-12 21:02:33 -05:00
|
|
|
// Cache computed type parameter uses (see type_use.rs)
|
2013-06-13 02:19:50 -05:00
|
|
|
type_use_cache: HashMap<ast::def_id, @~[type_use::type_uses]>,
|
2013-06-12 21:02:33 -05:00
|
|
|
// Cache generated vtables
|
2013-06-13 02:19:50 -05:00
|
|
|
vtables: HashMap<mono_id, ValueRef>,
|
2013-06-12 21:02:33 -05:00
|
|
|
// Cache of constant strings,
|
2013-06-13 02:19:50 -05:00
|
|
|
const_cstr_cache: HashMap<@str, ValueRef>,
|
2013-06-12 21:02:33 -05:00
|
|
|
|
|
|
|
// Reverse-direction for const ptrs cast from globals.
|
|
|
|
// Key is an int, cast from a ValueRef holding a *T,
|
|
|
|
// Val is a ValueRef holding a *[T].
|
|
|
|
//
|
|
|
|
// Needed because LLVM loses pointer->pointee association
|
|
|
|
// when we ptrcast, and we have to ptrcast during translation
|
|
|
|
// of a [T] const because we form a slice, a [*T,int] pair, not
|
|
|
|
// a pointer to an LLVM array type.
|
2013-06-13 02:19:50 -05:00
|
|
|
const_globals: HashMap<int, ValueRef>,
|
2013-06-12 21:02:33 -05:00
|
|
|
|
|
|
|
// Cache of emitted const values
|
2013-07-27 03:25:59 -05:00
|
|
|
const_values: HashMap<ast::NodeId, ValueRef>,
|
2013-06-12 21:02:33 -05:00
|
|
|
|
|
|
|
// Cache of external const values
|
2013-06-13 02:19:50 -05:00
|
|
|
extern_const_values: HashMap<ast::def_id, ValueRef>,
|
2013-06-12 21:02:33 -05:00
|
|
|
|
2013-06-14 00:38:17 -05:00
|
|
|
impl_method_cache: HashMap<(ast::def_id, ast::ident), ast::def_id>,
|
|
|
|
|
2013-06-13 02:19:50 -05:00
|
|
|
module_data: HashMap<~str, ValueRef>,
|
2013-06-16 05:52:44 -05:00
|
|
|
lltypes: HashMap<ty::t, Type>,
|
|
|
|
llsizingtypes: HashMap<ty::t, Type>,
|
2013-06-13 02:19:50 -05:00
|
|
|
adt_reprs: HashMap<ty::t, @adt::Repr>,
|
|
|
|
symbol_hasher: hash::State,
|
|
|
|
type_hashcodes: HashMap<ty::t, @str>,
|
|
|
|
type_short_names: HashMap<ty::t, ~str>,
|
|
|
|
all_llvm_symbols: HashSet<@str>,
|
2013-06-12 21:02:33 -05:00
|
|
|
tcx: ty::ctxt,
|
|
|
|
maps: astencode::Maps,
|
2013-06-22 17:38:02 -05:00
|
|
|
stats: @mut Stats,
|
2013-06-12 21:02:33 -05:00
|
|
|
upcalls: @upcall::Upcalls,
|
2013-06-15 05:16:47 -05:00
|
|
|
tydesc_type: Type,
|
|
|
|
int_type: Type,
|
|
|
|
float_type: Type,
|
|
|
|
opaque_vec_type: Type,
|
2013-06-12 21:02:33 -05:00
|
|
|
builder: BuilderRef_res,
|
|
|
|
crate_map: ValueRef,
|
|
|
|
// Set when at least one function uses GC. Needed so that
|
|
|
|
// decl_gc_metadata knows whether to link to the module metadata, which
|
|
|
|
// is not emitted by LLVM's GC pass when no functions use GC.
|
2013-06-13 02:19:50 -05:00
|
|
|
uses_gc: bool,
|
2013-06-12 21:02:33 -05:00
|
|
|
dbg_cx: Option<debuginfo::DebugContext>,
|
2013-06-13 02:19:50 -05:00
|
|
|
do_not_commit_warning_issued: bool
|
2013-06-12 21:02:33 -05:00
|
|
|
}
|
2013-06-12 21:49:01 -05:00
|
|
|
|
|
|
|
impl CrateContext {
|
2013-06-18 11:39:16 -05:00
|
|
|
pub fn new(sess: session::Session,
|
|
|
|
name: &str,
|
|
|
|
tcx: ty::ctxt,
|
|
|
|
emap2: resolve::ExportMap2,
|
|
|
|
maps: astencode::Maps,
|
|
|
|
symbol_hasher: hash::State,
|
|
|
|
link_meta: LinkMeta,
|
2013-07-27 03:25:59 -05:00
|
|
|
reachable: @mut HashSet<ast::NodeId>)
|
2013-06-18 11:39:16 -05:00
|
|
|
-> CrateContext {
|
2013-06-12 21:49:01 -05:00
|
|
|
unsafe {
|
|
|
|
let llcx = llvm::LLVMContextCreate();
|
|
|
|
set_task_llcx(llcx);
|
2013-08-14 21:21:59 -05:00
|
|
|
let llmod = do name.with_c_str |buf| {
|
2013-08-03 19:13:14 -05:00
|
|
|
llvm::LLVMModuleCreateWithNameInContext(buf, llcx)
|
|
|
|
};
|
2013-06-12 21:49:01 -05:00
|
|
|
let data_layout: &str = sess.targ_cfg.target_strs.data_layout;
|
|
|
|
let targ_triple: &str = sess.targ_cfg.target_strs.target_triple;
|
2013-08-14 21:21:59 -05:00
|
|
|
do data_layout.with_c_str |buf| {
|
2013-08-03 19:13:14 -05:00
|
|
|
llvm::LLVMSetDataLayout(llmod, buf)
|
|
|
|
};
|
2013-08-14 21:21:59 -05:00
|
|
|
do targ_triple.with_c_str |buf| {
|
2013-08-03 19:13:14 -05:00
|
|
|
llvm::LLVMSetTarget(llmod, buf)
|
|
|
|
};
|
2013-06-12 21:49:01 -05:00
|
|
|
let targ_cfg = sess.targ_cfg;
|
2013-06-14 21:31:52 -05:00
|
|
|
|
2013-06-12 21:49:01 -05:00
|
|
|
let td = mk_target_data(sess.targ_cfg.target_strs.data_layout);
|
2013-06-14 22:16:03 -05:00
|
|
|
let mut tn = TypeNames::new();
|
2013-06-14 21:31:52 -05:00
|
|
|
|
2013-06-12 21:49:01 -05:00
|
|
|
let mut intrinsics = base::declare_intrinsics(llmod);
|
|
|
|
if sess.opts.extra_debuginfo {
|
|
|
|
base::declare_dbg_intrinsics(llmod, &mut intrinsics);
|
|
|
|
}
|
2013-06-15 05:16:47 -05:00
|
|
|
let int_type = Type::int(targ_cfg.arch);
|
|
|
|
let float_type = Type::float(targ_cfg.arch);
|
|
|
|
let tydesc_type = Type::tydesc(targ_cfg.arch);
|
|
|
|
let opaque_vec_type = Type::opaque_vec(targ_cfg.arch);
|
|
|
|
|
2013-06-16 05:52:44 -05:00
|
|
|
let mut str_slice_ty = Type::named_struct("str_slice");
|
|
|
|
str_slice_ty.set_struct_body([Type::i8p(), int_type], false);
|
2013-06-15 22:45:48 -05:00
|
|
|
|
2013-06-15 05:16:47 -05:00
|
|
|
tn.associate_type("tydesc", &tydesc_type);
|
2013-06-15 22:45:48 -05:00
|
|
|
tn.associate_type("str_slice", &str_slice_ty);
|
2013-06-15 05:16:47 -05:00
|
|
|
|
2013-06-12 21:49:01 -05:00
|
|
|
let crate_map = decl_crate_map(sess, link_meta, llmod);
|
|
|
|
let dbg_cx = if sess.opts.debuginfo {
|
2013-06-17 10:42:05 -05:00
|
|
|
Some(debuginfo::DebugContext::new(llmod, name.to_owned()))
|
2013-06-12 21:49:01 -05:00
|
|
|
} else {
|
|
|
|
None
|
|
|
|
};
|
|
|
|
|
2013-06-16 23:23:24 -05:00
|
|
|
if sess.count_llvm_insns() {
|
|
|
|
base::init_insn_ctxt()
|
|
|
|
}
|
|
|
|
|
2013-06-12 21:49:01 -05:00
|
|
|
CrateContext {
|
|
|
|
sess: sess,
|
|
|
|
llmod: llmod,
|
|
|
|
llcx: llcx,
|
|
|
|
td: td,
|
|
|
|
tn: tn,
|
2013-06-13 02:19:50 -05:00
|
|
|
externs: HashMap::new(),
|
2013-06-12 21:49:01 -05:00
|
|
|
intrinsics: intrinsics,
|
2013-06-13 02:19:50 -05:00
|
|
|
item_vals: HashMap::new(),
|
2013-06-12 21:49:01 -05:00
|
|
|
exp_map2: emap2,
|
|
|
|
reachable: reachable,
|
2013-06-13 02:19:50 -05:00
|
|
|
item_symbols: HashMap::new(),
|
2013-06-12 21:49:01 -05:00
|
|
|
link_meta: link_meta,
|
2013-06-13 02:19:50 -05:00
|
|
|
enum_sizes: HashMap::new(),
|
|
|
|
discrims: HashMap::new(),
|
|
|
|
discrim_symbols: HashMap::new(),
|
|
|
|
tydescs: HashMap::new(),
|
|
|
|
finished_tydescs: false,
|
|
|
|
external: HashMap::new(),
|
|
|
|
monomorphized: HashMap::new(),
|
|
|
|
monomorphizing: HashMap::new(),
|
|
|
|
type_use_cache: HashMap::new(),
|
|
|
|
vtables: HashMap::new(),
|
|
|
|
const_cstr_cache: HashMap::new(),
|
|
|
|
const_globals: HashMap::new(),
|
|
|
|
const_values: HashMap::new(),
|
|
|
|
extern_const_values: HashMap::new(),
|
2013-06-14 00:38:17 -05:00
|
|
|
impl_method_cache: HashMap::new(),
|
2013-06-13 02:19:50 -05:00
|
|
|
module_data: HashMap::new(),
|
|
|
|
lltypes: HashMap::new(),
|
|
|
|
llsizingtypes: HashMap::new(),
|
|
|
|
adt_reprs: HashMap::new(),
|
2013-06-12 21:49:01 -05:00
|
|
|
symbol_hasher: symbol_hasher,
|
2013-06-13 02:19:50 -05:00
|
|
|
type_hashcodes: HashMap::new(),
|
|
|
|
type_short_names: HashMap::new(),
|
|
|
|
all_llvm_symbols: HashSet::new(),
|
2013-06-12 21:49:01 -05:00
|
|
|
tcx: tcx,
|
|
|
|
maps: maps,
|
2013-06-22 17:38:02 -05:00
|
|
|
stats: @mut Stats {
|
2013-06-12 21:49:01 -05:00
|
|
|
n_static_tydescs: 0u,
|
|
|
|
n_glues_created: 0u,
|
|
|
|
n_null_glues: 0u,
|
|
|
|
n_real_glues: 0u,
|
|
|
|
n_fns: 0u,
|
|
|
|
n_monos: 0u,
|
|
|
|
n_inlines: 0u,
|
|
|
|
n_closures: 0u,
|
2013-06-28 13:15:34 -05:00
|
|
|
n_llvm_insns: 0u,
|
|
|
|
llvm_insn_ctxt: ~[],
|
2013-06-13 02:19:50 -05:00
|
|
|
llvm_insns: HashMap::new(),
|
2013-06-28 13:15:34 -05:00
|
|
|
fn_stats: ~[]
|
2013-06-12 21:49:01 -05:00
|
|
|
},
|
|
|
|
upcalls: upcall::declare_upcalls(targ_cfg, llmod),
|
|
|
|
tydesc_type: tydesc_type,
|
|
|
|
int_type: int_type,
|
|
|
|
float_type: float_type,
|
2013-06-15 05:16:47 -05:00
|
|
|
opaque_vec_type: opaque_vec_type,
|
2013-06-20 00:52:02 -05:00
|
|
|
builder: BuilderRef_res(llvm::LLVMCreateBuilderInContext(llcx)),
|
2013-06-12 21:49:01 -05:00
|
|
|
crate_map: crate_map,
|
2013-06-13 02:19:50 -05:00
|
|
|
uses_gc: false,
|
2013-06-12 21:49:01 -05:00
|
|
|
dbg_cx: dbg_cx,
|
2013-06-13 02:19:50 -05:00
|
|
|
do_not_commit_warning_issued: false
|
2013-06-12 21:49:01 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2013-07-21 08:33:40 -05:00
|
|
|
|
|
|
|
pub fn builder(@mut self) -> Builder {
|
|
|
|
Builder::new(self)
|
|
|
|
}
|
2013-08-11 12:29:14 -05:00
|
|
|
|
|
|
|
pub fn const_inbounds_gepi(&self,
|
|
|
|
pointer: ValueRef,
|
|
|
|
indices: &[uint]) -> ValueRef {
|
|
|
|
debug!("const_inbounds_gepi: pointer=%s indices=%?",
|
|
|
|
self.tn.val_to_str(pointer), indices);
|
|
|
|
let v: ~[ValueRef] =
|
2013-08-11 13:56:43 -05:00
|
|
|
indices.iter().map(|i| C_i32(*i as i32)).collect();
|
2013-08-11 12:29:14 -05:00
|
|
|
unsafe {
|
|
|
|
llvm::LLVMConstInBoundsGEP(pointer,
|
|
|
|
vec::raw::to_ptr(v),
|
|
|
|
indices.len() as c_uint)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn offsetof_gep(&self,
|
|
|
|
llptr_ty: Type,
|
|
|
|
indices: &[uint]) -> ValueRef {
|
|
|
|
/*!
|
|
|
|
* Returns the offset of applying the given GEP indices
|
|
|
|
* to an instance of `llptr_ty`. Similar to `offsetof` in C,
|
|
|
|
* except that `llptr_ty` must be a pointer type.
|
|
|
|
*/
|
|
|
|
|
|
|
|
unsafe {
|
|
|
|
let null = C_null(llptr_ty);
|
|
|
|
llvm::LLVMConstPtrToInt(self.const_inbounds_gepi(null, indices),
|
|
|
|
self.int_type.to_ref())
|
|
|
|
}
|
|
|
|
}
|
2013-06-12 21:49:01 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[unsafe_destructor]
|
|
|
|
impl Drop for CrateContext {
|
2013-06-20 20:06:13 -05:00
|
|
|
fn drop(&self) {
|
2013-07-12 03:38:44 -05:00
|
|
|
unset_task_llcx();
|
2013-06-12 21:49:01 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-14 03:43:31 -05:00
|
|
|
static task_local_llcx_key: local_data::Key<@ContextRef> = &local_data::Key;
|
2013-07-12 03:38:44 -05:00
|
|
|
|
2013-06-12 21:49:01 -05:00
|
|
|
pub fn task_llcx() -> ContextRef {
|
2013-08-04 16:59:36 -05:00
|
|
|
let opt = local_data::get(task_local_llcx_key, |k| k.map_move(|k| *k));
|
2013-06-12 21:49:01 -05:00
|
|
|
*opt.expect("task-local LLVMContextRef wasn't ever set!")
|
|
|
|
}
|
|
|
|
|
2013-07-12 03:38:44 -05:00
|
|
|
fn set_task_llcx(c: ContextRef) {
|
2013-07-09 19:25:28 -05:00
|
|
|
local_data::set(task_local_llcx_key, @c);
|
2013-06-12 21:49:01 -05:00
|
|
|
}
|
|
|
|
|
2013-07-12 03:38:44 -05:00
|
|
|
fn unset_task_llcx() {
|
2013-07-09 19:25:28 -05:00
|
|
|
local_data::pop(task_local_llcx_key);
|
2013-06-12 21:49:01 -05:00
|
|
|
}
|