use lib::llvm::llvm;
use lib;
use middle::lang_items::LangItem;
-use middle::trans::base;
use middle::trans::build;
use middle::trans::cleanup;
use middle::trans::datum;
use middle::ty;
use middle::typeck;
use util::ppaux::Repr;
+use util::nodemap::NodeMap;
use arena::TypedArena;
+use collections::HashMap;
use std::c_str::ToCStr;
use std::cell::{Cell, RefCell};
-use collections::HashMap;
use std::libc::{c_uint, c_longlong, c_ulonglong, c_char};
use syntax::ast::Ident;
use syntax::ast;
fn type_is_newtype_immediate(ccx: &CrateContext, ty: ty::t) -> bool {
match ty::get(ty).sty {
ty::ty_struct(def_id, ref substs) => {
- let fields = ty::struct_fields(ccx.tcx, def_id, substs);
+ let fields = ty::struct_fields(ccx.tcx(), def_id, substs);
fields.len() == 1 &&
- fields[0].ident.name == token::special_idents::unnamed_field.name &&
- type_is_immediate(ccx, fields[0].mt.ty)
+ fields.get(0).ident.name ==
+ token::special_idents::unnamed_field.name &&
+ type_is_immediate(ccx, fields.get(0).mt.ty)
}
_ => false
}
pub fn type_is_immediate(ccx: &CrateContext, ty: ty::t) -> bool {
use middle::trans::machine::llsize_of_alloc;
use middle::trans::type_of::sizing_type_of;
- let tcx = ccx.tcx;
+ let tcx = ccx.tcx();
let simple = ty::type_is_scalar(ty) || ty::type_is_boxed(ty) ||
ty::type_is_unique(ty) || ty::type_is_region_ptr(ty) ||
type_is_newtype_immediate(ccx, ty) || ty::type_is_bot(ty) ||
* return type (in order to aid with C ABI compatibility).
*/
- ty::type_is_nil(ty) || ty::type_is_bot(ty) || ty::type_is_empty(ccx.tcx, ty)
+ ty::type_is_nil(ty) || ty::type_is_bot(ty) || ty::type_is_empty(ccx.tcx(), ty)
}
+/// Generates a unique symbol based off the name given. This is used to create
+/// unique symbols for things like closures.
pub fn gensym_name(name: &str) -> PathElem {
- PathName(token::gensym(name))
+ let num = token::gensym(name);
+ // use one colon which will get translated to a period by the mangler, and
+ // we're guaranteed that `num` is globally unique for this crate.
+ PathName(token::gensym(format!("{}:{}", name, num)))
}
pub struct tydesc_info {
n_llvm_insns: Cell<uint>,
llvm_insns: RefCell<HashMap<~str, uint>>,
// (ident, time-in-ms, llvm-instructions)
- fn_stats: RefCell<~[(~str, uint, uint)]>,
+ fn_stats: RefCell<Vec<(~str, uint, uint)> >,
}
pub struct BuilderRef_res {
- B: BuilderRef,
+ b: BuilderRef,
}
impl Drop for BuilderRef_res {
fn drop(&mut self) {
unsafe {
- llvm::LLVMDisposeBuilder(self.B);
+ llvm::LLVMDisposeBuilder(self.b);
}
}
}
-pub fn BuilderRef_res(B: BuilderRef) -> BuilderRef_res {
+pub fn BuilderRef_res(b: BuilderRef) -> BuilderRef_res {
BuilderRef_res {
- B: B
+ b: b
}
}
// Here `self_ty` is the real type of the self parameter to this method. It
// will only be set in the case of default methods.
pub struct param_substs {
- tys: ~[ty::t],
+ tys: Vec<ty::t> ,
self_ty: Option<ty::t>,
vtables: Option<typeck::vtable_res>,
self_vtables: Option<typeck::vtable_param_res>
}
}
-fn param_substs_to_str(this: ¶m_substs, tcx: ty::ctxt) -> ~str {
+fn param_substs_to_str(this: ¶m_substs, tcx: &ty::ctxt) -> ~str {
format!("param_substs \\{tys:{}, vtables:{}\\}",
this.tys.repr(tcx),
this.vtables.repr(tcx))
}
impl Repr for param_substs {
- fn repr(&self, tcx: ty::ctxt) -> ~str {
+ fn repr(&self, tcx: &ty::ctxt) -> ~str {
param_substs_to_str(self, tcx)
}
}
// work around bizarre resolve errors
-type RvalueDatum = datum::Datum<datum::Rvalue>;
-type LvalueDatum = datum::Datum<datum::Lvalue>;
+pub type RvalueDatum = datum::Datum<datum::Rvalue>;
+pub type LvalueDatum = datum::Datum<datum::Lvalue>;
// Function context. Every LLVM function we create will have one of
// these.
caller_expects_out_pointer: bool,
// Maps arguments to allocas created for them in llallocas.
- llargs: RefCell<HashMap<ast::NodeId, LvalueDatum>>,
+ llargs: RefCell<NodeMap<LvalueDatum>>,
// Maps the def_ids for local variables to the allocas created for
// them in llallocas.
- lllocals: RefCell<HashMap<ast::NodeId, LvalueDatum>>,
+ lllocals: RefCell<NodeMap<LvalueDatum>>,
// Same as above, but for closure upvars
- llupvars: RefCell<HashMap<ast::NodeId, ValueRef>>,
+ llupvars: RefCell<NodeMap<ValueRef>>,
// The NodeId of the function, or -1 if it doesn't correspond to
// a user-defined function.
block_arena: &'a TypedArena<Block<'a>>,
// This function's enclosing crate context.
- ccx: @CrateContext,
+ ccx: &'a CrateContext,
// Used and maintained by the debuginfo module.
debug_context: debuginfo::FunctionDebugContext,
// Cleanup scopes.
- scopes: RefCell<~[cleanup::CleanupScope<'a>]>,
+ scopes: RefCell<Vec<cleanup::CleanupScope<'a>> >,
}
impl<'a> FunctionContext<'a> {
pub fn get_llreturn(&self) -> BasicBlockRef {
if self.llreturn.get().is_none() {
- self.llreturn.set(Some(base::mk_return_basic_block(self.llfn)));
+
+ self.llreturn.set(Some(unsafe {
+ "return".with_c_str(|buf| {
+ llvm::LLVMAppendBasicBlockInContext(self.ccx.llcx, self.llfn, buf)
+ })
+ }))
}
self.llreturn.get().unwrap()
}
}
-pub fn warn_not_to_commit(ccx: &mut CrateContext, msg: &str) {
- if !ccx.do_not_commit_warning_issued.get() {
- ccx.do_not_commit_warning_issued.set(true);
- ccx.sess.warn(msg.to_str() + " -- do not commit like this!");
- }
-}
-
// Heap selectors. Indicate which heap something should go on.
#[deriving(Eq)]
pub enum heap {
})
}
- pub fn ccx(&self) -> @CrateContext { self.fcx.ccx }
- pub fn tcx(&self) -> ty::ctxt {
- self.fcx.ccx.tcx
+ pub fn ccx(&self) -> &'a CrateContext { self.fcx.ccx }
+ pub fn tcx(&self) -> &'a ty::ctxt {
+ &self.fcx.ccx.tcx
}
- pub fn sess(&self) -> Session { self.fcx.ccx.sess }
+ pub fn sess(&self) -> &'a Session { self.fcx.ccx.sess() }
pub fn ident(&self, ident: Ident) -> ~str {
token::get_ident(ident).get().to_str()
}
pub fn def(&self, nid: ast::NodeId) -> ast::Def {
- let def_map = self.tcx().def_map.borrow();
- match def_map.get().find(&nid) {
+ match self.tcx().def_map.borrow().find(&nid) {
Some(&v) => v,
None => {
self.tcx().sess.bug(format!(
}
}
-pub fn C_nil() -> ValueRef {
- C_struct([], false)
+pub fn C_nil(ccx: &CrateContext) -> ValueRef {
+ C_struct(ccx, [], false)
}
-pub fn C_bool(val: bool) -> ValueRef {
- C_integral(Type::bool(), val as u64, false)
+pub fn C_bool(ccx: &CrateContext, val: bool) -> ValueRef {
+ C_integral(Type::bool(ccx), val as u64, false)
}
-pub fn C_i1(val: bool) -> ValueRef {
- C_integral(Type::i1(), val as u64, false)
+pub fn C_i1(ccx: &CrateContext, val: bool) -> ValueRef {
+ C_integral(Type::i1(ccx), val as u64, false)
}
-pub fn C_i32(i: i32) -> ValueRef {
- return C_integral(Type::i32(), i as u64, true);
+pub fn C_i32(ccx: &CrateContext, i: i32) -> ValueRef {
+ C_integral(Type::i32(ccx), i as u64, true)
}
-pub fn C_i64(i: i64) -> ValueRef {
- return C_integral(Type::i64(), i as u64, true);
+pub fn C_i64(ccx: &CrateContext, i: i64) -> ValueRef {
+ C_integral(Type::i64(ccx), i as u64, true)
}
-pub fn C_u64(i: u64) -> ValueRef {
- return C_integral(Type::i64(), i, false);
+pub fn C_u64(ccx: &CrateContext, i: u64) -> ValueRef {
+ C_integral(Type::i64(ccx), i, false)
}
-pub fn C_int(cx: &CrateContext, i: int) -> ValueRef {
- return C_integral(cx.int_type, i as u64, true);
+pub fn C_int(ccx: &CrateContext, i: int) -> ValueRef {
+ C_integral(ccx.int_type, i as u64, true)
}
-pub fn C_uint(cx: &CrateContext, i: uint) -> ValueRef {
- return C_integral(cx.int_type, i as u64, false);
+pub fn C_uint(ccx: &CrateContext, i: uint) -> ValueRef {
+ C_integral(ccx.int_type, i as u64, false)
}
-pub fn C_u8(i: uint) -> ValueRef {
- return C_integral(Type::i8(), i as u64, false);
+pub fn C_u8(ccx: &CrateContext, i: uint) -> ValueRef {
+ C_integral(Type::i8(ccx), i as u64, false)
}
// our boxed-and-length-annotated strings.
pub fn C_cstr(cx: &CrateContext, s: InternedString) -> ValueRef {
unsafe {
- {
- let const_cstr_cache = cx.const_cstr_cache.borrow();
- match const_cstr_cache.get().find(&s) {
- Some(&llval) => return llval,
- None => ()
- }
+ match cx.const_cstr_cache.borrow().find(&s) {
+ Some(&llval) => return llval,
+ None => ()
}
let sc = llvm::LLVMConstStringInContext(cx.llcx,
llvm::LLVMSetGlobalConstant(g, True);
lib::llvm::SetLinkage(g, lib::llvm::InternalLinkage);
- let mut const_cstr_cache = cx.const_cstr_cache.borrow_mut();
- const_cstr_cache.get().insert(s, g);
+ cx.const_cstr_cache.borrow_mut().insert(s, g);
g
}
}
pub fn C_str_slice(cx: &CrateContext, s: InternedString) -> ValueRef {
unsafe {
let len = s.get().len();
- let cs = llvm::LLVMConstPointerCast(C_cstr(cx, s), Type::i8p().to_ref());
- C_struct([cs, C_uint(cx, len)], false)
+ let cs = llvm::LLVMConstPointerCast(C_cstr(cx, s), Type::i8p(cx).to_ref());
+ C_struct(cx, [cs, C_uint(cx, len)], false)
}
}
pub fn C_binary_slice(cx: &CrateContext, data: &[u8]) -> ValueRef {
unsafe {
let len = data.len();
- let lldata = C_bytes(data);
+ let lldata = C_bytes(cx, data);
let gsym = token::gensym("binary");
let g = format!("binary{}", gsym).with_c_str(|buf| {
llvm::LLVMSetGlobalConstant(g, True);
lib::llvm::SetLinkage(g, lib::llvm::InternalLinkage);
- let cs = llvm::LLVMConstPointerCast(g, Type::i8p().to_ref());
- C_struct([cs, C_uint(cx, len)], false)
- }
-}
-
-pub fn C_zero_byte_arr(size: uint) -> ValueRef {
- unsafe {
- let mut i = 0u;
- let mut elts: ~[ValueRef] = ~[];
- while i < size { elts.push(C_u8(0u)); i += 1u; }
- return llvm::LLVMConstArray(Type::i8().to_ref(),
- elts.as_ptr(), elts.len() as c_uint);
+ let cs = llvm::LLVMConstPointerCast(g, Type::i8p(cx).to_ref());
+ C_struct(cx, [cs, C_uint(cx, len)], false)
}
}
-pub fn C_struct(elts: &[ValueRef], packed: bool) -> ValueRef {
+pub fn C_struct(ccx: &CrateContext, elts: &[ValueRef], packed: bool) -> ValueRef {
unsafe {
-
- llvm::LLVMConstStructInContext(base::task_llcx(),
+ llvm::LLVMConstStructInContext(ccx.llcx,
elts.as_ptr(), elts.len() as c_uint,
packed as Bool)
}
}
-pub fn C_named_struct(T: Type, elts: &[ValueRef]) -> ValueRef {
+pub fn C_named_struct(t: Type, elts: &[ValueRef]) -> ValueRef {
unsafe {
- llvm::LLVMConstNamedStruct(T.to_ref(), elts.as_ptr(), elts.len() as c_uint)
+ llvm::LLVMConstNamedStruct(t.to_ref(), elts.as_ptr(), elts.len() as c_uint)
}
}
}
}
-pub fn C_bytes(bytes: &[u8]) -> ValueRef {
+pub fn C_bytes(ccx: &CrateContext, bytes: &[u8]) -> ValueRef {
unsafe {
let ptr = bytes.as_ptr() as *c_char;
- return llvm::LLVMConstStringInContext(base::task_llcx(), ptr, bytes.len() as c_uint, True);
+ return llvm::LLVMConstStringInContext(ccx.llcx, ptr, bytes.len() as c_uint, True);
}
}
}
// Used to identify cached monomorphized functions and vtables
-#[deriving(Eq,Hash)]
+#[deriving(Eq, TotalEq, Hash)]
pub enum mono_param_id {
- mono_precise(ty::t, Option<@~[mono_id]>),
+ mono_precise(ty::t, Option<@Vec<mono_id> >),
mono_any,
mono_repr(uint /* size */,
uint /* align */,
datum::RvalueMode),
}
-#[deriving(Eq,Hash)]
+#[deriving(Eq, TotalEq, Hash)]
pub enum MonoDataClass {
MonoBits, // Anything not treated differently from arbitrary integer data
MonoNonNull, // Non-null pointers (used for optional-pointer optimization)
}
}
-
-#[deriving(Eq,Hash)]
+#[deriving(Eq, TotalEq, Hash)]
pub struct mono_id_ {
def: ast::DefId,
- params: ~[mono_param_id]
-}
+ params: Vec<mono_param_id> }
pub type mono_id = @mono_id_;
pub fn monomorphize_type(bcx: &Block, t: ty::t) -> ty::t {
match bcx.fcx.param_substs {
Some(substs) => {
- ty::subst_tps(bcx.tcx(), substs.tys, substs.self_ty, t)
+ ty::subst_tps(bcx.tcx(), substs.tys.as_slice(), substs.self_ty, t)
}
_ => {
assert!(!ty::type_has_params(t));
pub fn expr_ty_adjusted(bcx: &Block, ex: &ast::Expr) -> ty::t {
let tcx = bcx.tcx();
- let t = ty::expr_ty_adjusted(tcx, ex);
+ let t = ty::expr_ty_adjusted(tcx, ex, &*bcx.ccx().maps.method_map.borrow());
monomorphize_type(bcx, t)
}
-pub fn node_id_type_params(bcx: &Block, id: ast::NodeId) -> ~[ty::t] {
+// Key used to lookup values supplied for type parameters in an expr.
+#[deriving(Eq)]
+pub enum ExprOrMethodCall {
+ // Type parameters for a path like `None::<int>`
+ ExprId(ast::NodeId),
+
+ // Type parameters for a method call like `a.foo::<int>()`
+ MethodCall(typeck::MethodCall)
+}
+
+pub fn node_id_type_params(bcx: &Block, node: ExprOrMethodCall) -> Vec<ty::t> {
let tcx = bcx.tcx();
- let params = ty::node_id_to_type_params(tcx, id);
+ let params = match node {
+ ExprId(id) => ty::node_id_to_type_params(tcx, id),
+ MethodCall(method_call) => {
+ bcx.ccx().maps.method_map.borrow().get(&method_call).substs.tps.clone()
+ }
+ };
if !params.iter().all(|t| !ty::type_needs_infer(*t)) {
bcx.sess().bug(
- format!("type parameters for node {} include inference types: {}",
- id, params.map(|t| bcx.ty_to_str(*t)).connect(",")));
+ format!("type parameters for node {:?} include inference types: {}",
+ node, params.map(|t| bcx.ty_to_str(*t)).connect(",")));
}
match bcx.fcx.param_substs {
Some(substs) => {
params.iter().map(|t| {
- ty::subst_tps(tcx, substs.tys, substs.self_ty, *t)
+ ty::subst_tps(tcx, substs.tys.as_slice(), substs.self_ty, *t)
}).collect()
}
_ => params
}
}
-pub fn node_vtables(bcx: &Block, id: ast::NodeId)
+pub fn node_vtables(bcx: &Block, id: typeck::MethodCall)
-> Option<typeck::vtable_res> {
let vtable_map = bcx.ccx().maps.vtable_map.borrow();
- let raw_vtables = vtable_map.get().find(&id);
+ let raw_vtables = vtable_map.find(&id);
raw_vtables.map(|vts| resolve_vtables_in_fn_ctxt(bcx.fcx, *vts))
}
// vtables. This should eliminate any vtable_params.
pub fn resolve_vtables_in_fn_ctxt(fcx: &FunctionContext, vts: typeck::vtable_res)
-> typeck::vtable_res {
- resolve_vtables_under_param_substs(fcx.ccx.tcx,
+ resolve_vtables_under_param_substs(fcx.ccx.tcx(),
fcx.param_substs,
vts)
}
-pub fn resolve_vtables_under_param_substs(tcx: ty::ctxt,
+pub fn resolve_vtables_under_param_substs(tcx: &ty::ctxt,
param_substs: Option<@param_substs>,
vts: typeck::vtable_res)
-> typeck::vtable_res {
}
pub fn resolve_param_vtables_under_param_substs(
- tcx: ty::ctxt,
+ tcx: &ty::ctxt,
param_substs: Option<@param_substs>,
ds: typeck::vtable_param_res)
-> typeck::vtable_param_res {
-pub fn resolve_vtable_under_param_substs(tcx: ty::ctxt,
+pub fn resolve_vtable_under_param_substs(tcx: &ty::ctxt,
param_substs: Option<@param_substs>,
vt: &typeck::vtable_origin)
-> typeck::vtable_origin {
let tys = match param_substs {
Some(substs) => {
tys.iter().map(|t| {
- ty::subst_tps(tcx, substs.tys, substs.self_ty, *t)
+ ty::subst_tps(tcx,
+ substs.tys.as_slice(),
+ substs.self_ty,
+ *t)
}).collect()
}
- _ => tys.to_owned()
+ _ => Vec::from_slice(tys.as_slice())
};
typeck::vtable_static(
trait_id, tys,
}
}
-pub fn find_vtable(tcx: ty::ctxt,
+pub fn find_vtable(tcx: &ty::ctxt,
ps: ¶m_substs,
n_param: typeck::param_index,
n_bound: uint)
typeck::param_numbered(n) => {
let tables = ps.vtables
.expect("vtables missing where they are needed");
- tables[n]
+ *tables.get(n)
}
};
- param_bounds[n_bound].clone()
+ param_bounds.get(n_bound).clone()
}
-pub fn dummy_substs(tps: ~[ty::t]) -> ty::substs {
+pub fn dummy_substs(tps: Vec<ty::t> ) -> ty::substs {
substs {
regions: ty::ErasedRegions,
self_ty: None,
pub fn filename_and_line_num_from_span(bcx: &Block, span: Span)
-> (ValueRef, ValueRef) {
- let loc = bcx.sess().parse_sess.cm.lookup_char_pos(span.lo);
+ let loc = bcx.sess().codemap().lookup_char_pos(span.lo);
let filename_cstr = C_cstr(bcx.ccx(),
token::intern_and_get_ident(loc.file.name));
- let filename = build::PointerCast(bcx, filename_cstr, Type::i8p());
+ let filename = build::PointerCast(bcx, filename_cstr, Type::i8p(bcx.ccx()));
let line = C_int(bcx.ccx(), loc.line as int);
(filename, line)
}
// Casts a Rust bool value to an i1.
pub fn bool_to_i1(bcx: &Block, llval: ValueRef) -> ValueRef {
- build::ICmp(bcx, lib::llvm::IntNE, llval, C_bool(false))
+ build::ICmp(bcx, lib::llvm::IntNE, llval, C_bool(bcx.ccx(), false))
}
pub fn langcall(bcx: &Block,