diff --git a/src/librustc/middle/trans/_match.rs b/src/librustc/middle/trans/_match.rs index ebb813f6d2433..f4080f85dc181 100644 --- a/src/librustc/middle/trans/_match.rs +++ b/src/librustc/middle/trans/_match.rs @@ -199,7 +199,7 @@ use driver::session::FullDebugInfo; use lib::llvm::{llvm, ValueRef, BasicBlockRef}; use middle::const_eval; use middle::borrowck::root_map_key; -use middle::lang_items::{UniqStrEqFnLangItem, StrEqFnLangItem}; +use middle::lang_items::StrEqFnLangItem; use middle::pat_util::*; use middle::resolve::DefMap; use middle::trans::adt; @@ -1278,30 +1278,20 @@ fn compare_values<'a>( -> Result<'a> { let _icx = push_ctxt("compare_values"); if ty::type_is_scalar(rhs_t) { - let rs = compare_scalar_types(cx, lhs, rhs, rhs_t, ast::BiEq); - return rslt(rs.bcx, rs.val); + return compare_scalar_types(cx, lhs, rhs, rhs_t, ast::BiEq); } match ty::get(rhs_t).sty { - ty::ty_str(ty::vstore_uniq) => { - let scratch_lhs = alloca(cx, val_ty(lhs), "__lhs"); - Store(cx, lhs, scratch_lhs); - let scratch_rhs = alloca(cx, val_ty(rhs), "__rhs"); - Store(cx, rhs, scratch_rhs); - let did = langcall(cx, None, - format!("comparison of `{}`", cx.ty_to_str(rhs_t)), - UniqStrEqFnLangItem); - let result = callee::trans_lang_call(cx, did, [scratch_lhs, scratch_rhs], None); - Result { - bcx: result.bcx, - val: bool_to_i1(result.bcx, result.val) - } - } ty::ty_str(_) => { let did = langcall(cx, None, format!("comparison of `{}`", cx.ty_to_str(rhs_t)), StrEqFnLangItem); - let result = callee::trans_lang_call(cx, did, [lhs, rhs], None); + let result = callee::trans_call(cx, None, + callee::Fn(callee::trans_fn_ref_with_vtables(cx, did, ExprId(0), [], None)), + [lhs, rhs].iter(), |bcx, &val| { + DatumBlock(bcx, Datum(val, rhs_t, RvalueExpr(Rvalue(ByRef)))) + }, + None); Result { bcx: result.bcx, val: bool_to_i1(result.bcx, result.val) diff --git a/src/librustc/middle/trans/asm.rs b/src/librustc/middle/trans/asm.rs index f4ce7c3c6a692..e0e16b5dc3d9c 100644 --- a/src/librustc/middle/trans/asm.rs +++ b/src/librustc/middle/trans/asm.rs @@ -48,15 +48,13 @@ pub fn trans_inline_asm<'a>(bcx: &'a Block<'a>, ia: &ast::InlineAsm) // Now the input operands let inputs = ia.inputs.map(|&(ref c, input)| { constraints.push((*c).clone()); - - let in_datum = unpack_datum!(bcx, expr::trans(bcx, input)); - unpack_result!(bcx, { - callee::trans_arg_datum(bcx, - expr_ty(bcx, input), - in_datum, - cleanup::CustomScope(temp_scope), - callee::DontAutorefArg) - }) + let input = expr::trans(bcx, input); + let input_ty = input.datum.ty; + let input = unpack_datum!(bcx, { + callee::trans_arg_datum(input, input_ty, + cleanup::CustomScope(temp_scope)) + }); + input.val }); // no failure occurred preparing operands, no need to cleanup diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index a00bcdd7037d8..adf3e182acfa1 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -356,7 +356,7 @@ pub fn malloc_raw_dyn<'a>( let r = callee::trans_lang_call( bcx, require_alloc_fn(bcx, t, ExchangeMallocFnLangItem), - [size], + [datum::pod_value(ccx.tcx(), size, ty::mk_uint())], None); rslt(r.bcx, PointerCast(r.bcx, r.val, llty_value.ptr_to())) } else { @@ -378,13 +378,16 @@ pub fn malloc_raw_dyn<'a>( // Allocate space: let drop_glue = glue::get_drop_glue(ccx, t); + let drop_glue = PointerCast(bcx, drop_glue, + Type::glue_fn(ccx, Type::i8p(ccx)).ptr_to()); let r = callee::trans_lang_call( bcx, langcall, [ - PointerCast(bcx, drop_glue, Type::glue_fn(ccx, Type::i8p(ccx)).ptr_to()), - size, - llalign + datum::pod_value(ccx.tcx(), drop_glue, + ty::mk_imm_ptr(ccx.tcx(), ty::mk_nil())), + datum::pod_value(ccx.tcx(), size, ty::mk_uint()), + datum::pod_value(ccx.tcx(), llalign, ty::mk_uint()) ], None); rslt(r.bcx, PointerCast(r.bcx, r.val, llty)) @@ -535,11 +538,14 @@ pub fn get_res_dtor(ccx: &CrateContext, }; let vtables = typeck::check::vtable::trans_resolve_method(ccx.tcx(), did.node, &tsubsts); - let (val, _) = monomorphize::monomorphic_fn(ccx, did, &tsubsts, vtables, None, None); - - val + monomorphize::monomorphic_fn(ccx, did, &tsubsts, vtables, None, None).val } else if did.krate == ast::LOCAL_CRATE { - get_item_val(ccx, did.node) + match get_item_val(ccx, did.node) { + datum::LvalueDatum(_) => { + ccx.sess().bug("found Lvalue instead of PodValue for drop method"); + } + datum::PodValueDatum(datum) => datum.val + } } else { let tcx = ccx.tcx(); let name = csearch::get_symbol(&ccx.sess().cstore, did); @@ -857,9 +863,10 @@ pub fn fail_if_zero<'a>( }) } -pub fn trans_external_path(ccx: &CrateContext, did: ast::DefId, t: ty::t) -> ValueRef { +pub fn trans_external_path(ccx: &CrateContext, did: ast::DefId, t: ty::t) + -> datum::Datum { let name = csearch::get_symbol(&ccx.sess().cstore, did); - match ty::get(t).sty { + let llval = match ty::get(t).sty { ty::ty_bare_fn(ref fn_ty) => { match fn_ty.abis.for_target(ccx.sess().targ_cfg.os, ccx.sess().targ_cfg.arch) { @@ -891,7 +898,8 @@ pub fn trans_external_path(ccx: &CrateContext, did: ast::DefId, t: ty::t) -> Val get_extern_const(&mut *ccx.externs.borrow_mut(), ccx.llmod, name, llty) } - } + }; + datum::pod_value(ccx.tcx(), llval, t) } pub fn invoke<'a>( @@ -1621,7 +1629,12 @@ pub fn trans_enum_def(ccx: &CrateContext, enum_definition: &ast::EnumDef, match variant.node.kind { ast::TupleVariantKind(ref args) if args.len() > 0 => { - let llfn = get_item_val(ccx, variant.node.id); + let llfn = match get_item_val(ccx, variant.node.id) { + datum::LvalueDatum(_) => { + ccx.sess().bug("found Lvalue instead of PodValue for method"); + } + datum::PodValueDatum(datum) => datum.val + }; trans_enum_variant(ccx, id, variant, args.as_slice(), disr_val, None, llfn); } @@ -1650,11 +1663,22 @@ pub fn trans_item(ccx: &CrateContext, item: &ast::Item) { match item.node { ast::ItemFn(decl, purity, _abis, ref generics, body) => { if purity == ast::ExternFn { - let llfndecl = get_item_val(ccx, item.id); + let llfn = match get_item_val(ccx, item.id) { + datum::LvalueDatum(_) => { + ccx.sess().bug("found Lvalue instead of PodValue for fn"); + } + datum::PodValueDatum(datum) => datum.val + }; foreign::trans_rust_fn_with_foreign_abi( - ccx, decl, body, item.attrs.as_slice(), llfndecl, item.id); + ccx, decl, body, item.attrs.as_slice(), + llfn, item.id); } else if !generics.is_type_parameterized() { - let llfn = get_item_val(ccx, item.id); + let llfn = match get_item_val(ccx, item.id) { + datum::LvalueDatum(_) => { + ccx.sess().bug("found Lvalue instead of PodValue for fn"); + } + datum::PodValueDatum(datum) => datum.val + }; trans_fn(ccx, decl, body, @@ -1727,9 +1751,14 @@ pub fn trans_struct_def(ccx: &CrateContext, struct_def: @ast::StructDef) { // We only need to translate a constructor if there are fields; // otherwise this is a unit-like struct. Some(ctor_id) if struct_def.fields.len() > 0 => { - let llfndecl = get_item_val(ccx, ctor_id); + let llfn = match get_item_val(ccx, ctor_id) { + datum::LvalueDatum(_) => { + ccx.sess().bug("found Lvalue instead of PodValue for struct ctor"); + } + datum::PodValueDatum(datum) => datum.val + }; trans_tuple_struct(ccx, struct_def.fields.as_slice(), - ctor_id, None, llfndecl); + ctor_id, None, llfn); } Some(_) | None => {} } @@ -1765,7 +1794,7 @@ fn register_fn(ccx: &CrateContext, sym: ~str, node_id: ast::NodeId, node_type: ty::t) - -> ValueRef { + -> datum::Datum { let f = match ty::get(node_type).sty { ty::ty_bare_fn(ref f) => { assert!(f.abis.is_rust() || f.abis.is_intrinsic()); @@ -1780,7 +1809,7 @@ fn register_fn(ccx: &CrateContext, f.sig.output, sym); finish_register_fn(ccx, sp, sym, node_id, llfn); - llfn + datum::pod_value(ccx.tcx(), llfn, node_type) } // only use this for foreign function ABIs and glue, use `register_fn` for Rust functions @@ -1841,7 +1870,12 @@ pub fn create_entry_wrapper(ccx: &CrateContext, Err(s) => { ccx.sess().fatal(s); } }; let start_fn = if start_def_id.krate == ast::LOCAL_CRATE { - get_item_val(ccx, start_def_id.node) + match get_item_val(ccx, start_def_id.node) { + datum::LvalueDatum(_) => { + ccx.sess().bug("found Lvalue instead of PodValue for start fn"); + } + datum::PodValueDatum(datum) => datum + } } else { let start_fn_type = csearch::get_type(ccx.tcx(), start_def_id).ty; @@ -1859,7 +1893,7 @@ pub fn create_entry_wrapper(ccx: &CrateContext, llvm::LLVMGetParam(llfn, 1) ) }; - (start_fn, args) + (start_fn.val, args) } else { debug!("using user-defined start fn"); let args = vec!( @@ -1899,22 +1933,21 @@ fn exported_name(ccx: &CrateContext, id: ast::NodeId, } } -pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef { +pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> datum::LvalueOrPod { debug!("get_item_val(id=`{:?}`)", id); - match ccx.item_vals.borrow().find_copy(&id) { - Some(v) => return v, + match ccx.item_vals.borrow().find(&id) { + Some(&datum) => return datum, None => {} } let mut foreign = false; - let item = ccx.tcx.map.get(id); - let val = match item { + let datum = match ccx.tcx.map.get(id) { ast_map::NodeItem(i) => { let ty = ty::node_id_to_type(ccx.tcx(), i.id); let sym = exported_name(ccx, id, ty, i.attrs.as_slice()); - let v = match i.node { + let datum = match i.node { ast::ItemStatic(_, _, expr) => { // If this static came from an external crate, then // we need to get the symbol from csearch instead of @@ -1936,7 +1969,6 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef { // LLVM type is not fully determined by the Rust type. let (v, inlineable) = consts::const_expr(ccx, expr, is_local); ccx.const_values.borrow_mut().insert(id, v); - let mut inlineable = inlineable; unsafe { let llty = llvm::LLVMTypeOf(v); @@ -1950,6 +1982,7 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef { // Apply the `unnamed_addr` attribute if // requested + let mut inlineable = inlineable; if attr::contains_name(i.attrs.as_slice(), "address_insignificant") { if ccx.reachable.contains(&id) { @@ -1984,17 +2017,17 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef { if !inlineable { debug!("{} not inlined", sym); - ccx.non_inlineable_statics.borrow_mut() - .insert(id); + ccx.non_inlineable_statics.borrow_mut().insert(id); } ccx.item_symbols.borrow_mut().insert(i.id, sym); - g + + datum::LvalueDatum(datum::Datum(g, ty, datum::Lvalue)) } } ast::ItemFn(_, purity, _, _, _) => { - let llfn = if purity != ast::ExternFn { + let datum = if purity != ast::ExternFn { register_fn(ccx, i.span, sym, i.id, ty) } else { foreign::register_rust_fn_with_foreign_abi(ccx, @@ -2002,24 +2035,31 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef { sym, i.id) }; - set_llvm_fn_attrs(i.attrs.as_slice(), llfn); - llfn + set_llvm_fn_attrs(i.attrs.as_slice(), datum.val); + datum::PodValueDatum(datum) } _ => fail!("get_item_val: weird result in table") }; - match attr::first_attr_value_str_by_name(i.attrs.as_slice(), + match attr::first_attr_value_str_by_name(i.attrs + .as_slice(), "link_section") { - Some(sect) => unsafe { - sect.get().with_c_str(|buf| { - llvm::LLVMSetSection(v, buf); - }) + Some(sect) => { + let val = match datum { + datum::LvalueDatum(datum) => datum.val, + datum::PodValueDatum(datum) => datum.val + }; + unsafe { + sect.get().with_c_str(|buf| { + llvm::LLVMSetSection(val, buf); + }) + } }, None => () } - v + datum } ast_map::NodeTraitMethod(trait_method) => { @@ -2030,77 +2070,81 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef { get_item_val()"); } ast::Provided(m) => { - register_method(ccx, id, m) + datum::PodValueDatum(register_method(ccx, id, m)) } } } ast_map::NodeMethod(m) => { - register_method(ccx, id, m) + datum::PodValueDatum(register_method(ccx, id, m)) } ast_map::NodeForeignItem(ni) => { + let ty = ty::node_id_to_type(ccx.tcx(), ni.id); foreign = true; match ni.node { ast::ForeignItemFn(..) => { let abis = ccx.tcx.map.get_foreign_abis(id); - foreign::register_foreign_item_fn(ccx, abis, ni) + let llfn = foreign::register_foreign_item_fn(ccx, abis, ni); + datum::PodValueDatum(datum::pod_value(ccx.tcx(), llfn, ty)) } ast::ForeignItemStatic(..) => { - foreign::register_static(ccx, ni) + let llref = foreign::register_static(ccx, ni); + datum::LvalueDatum(datum::Datum(llref, ty, datum::Lvalue)) } } } ast_map::NodeVariant(ref v) => { - let llfn; - let args = match v.node.kind { - ast::TupleVariantKind(ref args) => args, + match v.node.kind { + ast::TupleVariantKind(ref args) => { + assert!(args.len() != 0u); + let ty = ty::node_id_to_type(ccx.tcx(), id); + let parent = ccx.tcx.map.get_parent(id); + let enm = ccx.tcx.map.expect_item(parent); + let sym = exported_name(ccx, + id, + ty, + enm.attrs.as_slice()); + + let datum = match enm.node { + ast::ItemEnum(_, _) => { + register_fn(ccx, (*v).span, sym, id, ty) + } + _ => fail!("NodeVariant, shouldn't happen") + }; + set_inline_hint(datum.val); + datum::PodValueDatum(datum) + } ast::StructVariantKind(_) => { fail!("struct variant kind unexpected in get_item_val") } - }; - assert!(args.len() != 0u); - let ty = ty::node_id_to_type(ccx.tcx(), id); - let parent = ccx.tcx.map.get_parent(id); - let enm = ccx.tcx.map.expect_item(parent); - let sym = exported_name(ccx, - id, - ty, - enm.attrs.as_slice()); - - llfn = match enm.node { - ast::ItemEnum(_, _) => { - register_fn(ccx, (*v).span, sym, id, ty) - } - _ => fail!("NodeVariant, shouldn't happen") - }; - set_inline_hint(llfn); - llfn + } } ast_map::NodeStructCtor(struct_def) => { // Only register the constructor if this is a tuple-like struct. - let ctor_id = match struct_def.ctor_id { + match struct_def.ctor_id { None => { ccx.sess().bug("attempt to register a constructor of \ a non-tuple-like struct") } - Some(ctor_id) => ctor_id, - }; - let parent = ccx.tcx.map.get_parent(id); - let struct_item = ccx.tcx.map.expect_item(parent); - let ty = ty::node_id_to_type(ccx.tcx(), ctor_id); - let sym = exported_name(ccx, - id, - ty, - struct_item.attrs - .as_slice()); - let llfn = register_fn(ccx, struct_item.span, - sym, ctor_id, ty); - set_inline_hint(llfn); - llfn + Some(ctor_id) => { + let parent = ccx.tcx.map.get_parent(id); + let struct_item = ccx.tcx.map.expect_item(parent); + let ty = ty::node_id_to_type(ccx.tcx(), ctor_id); + let sym = exported_name(ccx, + id, + ty, + struct_item.attrs + .as_slice()); + let datum = register_fn(ccx, struct_item.span, + sym, ctor_id, ty); + set_inline_hint(datum.val); + datum::PodValueDatum(datum) + } + } } ref variant => { @@ -2113,22 +2157,26 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef { // linkage b/c that doesn't quite make sense. Otherwise items can // have internal linkage if they're not reachable. if !foreign && !ccx.reachable.contains(&id) { + let val = match datum { + datum::LvalueDatum(datum) => datum.val, + datum::PodValueDatum(datum) => datum.val + }; lib::llvm::SetLinkage(val, lib::llvm::InternalLinkage); } - ccx.item_vals.borrow_mut().insert(id, val); - val + ccx.item_vals.borrow_mut().insert(id, datum); + datum } fn register_method(ccx: &CrateContext, id: ast::NodeId, - m: &ast::Method) -> ValueRef { + m: &ast::Method) -> datum::Datum { let mty = ty::node_id_to_type(ccx.tcx(), id); let sym = exported_name(ccx, id, mty, m.attrs.as_slice()); - let llfn = register_fn(ccx, m.span, sym, id, mty); - set_llvm_fn_attrs(m.attrs.as_slice(), llfn); - llfn + let datum = register_fn(ccx, m.span, sym, id, mty); + set_llvm_fn_attrs(m.attrs.as_slice(), datum.val); + datum } pub fn vp2i(cx: &Block, v: ValueRef) -> ValueRef { @@ -2355,8 +2403,13 @@ pub fn fill_crate_map(ccx: &CrateContext, map: ValueRef) { let event_loop_factory = match ccx.tcx.lang_items.event_loop_factory() { Some(did) => unsafe { if is_local(did) { - llvm::LLVMConstPointerCast(get_item_val(ccx, did.node), - ccx.int_type.ptr_to().to_ref()) + let llfn = match get_item_val(ccx, did.node) { + datum::LvalueDatum(_) => { + ccx.sess().bug("found Lvalue instead of PodValue for event loop factory"); + } + datum::PodValueDatum(datum) => datum.val + }; + llvm::LLVMConstPointerCast(llfn, ccx.int_type.ptr_to().to_ref()) } else { let name = csearch::get_symbol(&ccx.sess().cstore, did); let global = name.with_c_str(|buf| { diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs index 92b97cdfc9f02..fb453db66af0a 100644 --- a/src/librustc/middle/trans/callee.rs +++ b/src/librustc/middle/trans/callee.rs @@ -20,19 +20,15 @@ use std::slice; use back::abi; use driver::session; -use lib::llvm::{ValueRef, NoAliasAttribute, StructRetAttribute}; +use lib::llvm::{NoAliasAttribute, StructRetAttribute}; use lib::llvm::llvm; -use metadata::csearch; use middle::trans::base; use middle::trans::base::*; use middle::trans::build::*; -use middle::trans::callee; use middle::trans::cleanup; use middle::trans::cleanup::CleanupMethods; -use middle::trans::common; use middle::trans::common::*; use middle::trans::datum::*; -use middle::trans::datum::Datum; use middle::trans::expr; use middle::trans::glue; use middle::trans::inline; @@ -54,53 +50,40 @@ use syntax::ast; use syntax::abi::AbiSet; use syntax::ast_map; -pub struct MethodData { - llfn: ValueRef, - llself: ValueRef, -} - -pub enum CalleeData { +pub enum Callee { Closure(Datum), // Represents a (possibly monomorphized) top-level fn item or method // item. Note that this is just the fn-ptr and is not a Rust closure // value (which is a pair). - Fn(/* llfn */ ValueRef), + Fn(Datum), - TraitMethod(MethodData) + // Method type and index for a trait object method call. + TraitMethod(ty::t, uint) } -pub struct Callee<'a> { - bcx: &'a Block<'a>, - data: CalleeData -} - -fn trans<'a>(bcx: &'a Block<'a>, expr: &ast::Expr) -> Callee<'a> { +pub fn trans<'a>(bcx: &'a Block<'a>, expr: &ast::Expr) -> (&'a Block<'a>, Callee) { let _icx = push_ctxt("trans_callee"); debug!("callee::trans(expr={})", expr.repr(bcx.tcx())); - // pick out special kinds of expressions that can be called: - match expr.node { - ast::ExprPath(_) => { - return trans_def(bcx, bcx.def(expr.id), expr); - } - _ => {} - } - - // any other expressions are closures: - return datum_callee(bcx, expr); + return match expr.node { + // pick out special kinds of expressions that can be called: + ast::ExprPath(_) => trans_def(bcx, bcx.def(expr.id), expr), + // any other expressions are closures: + _ => datum_callee(bcx, expr) + }; - fn datum_callee<'a>(bcx: &'a Block<'a>, expr: &ast::Expr) -> Callee<'a> { - let DatumBlock {bcx: mut bcx, datum} = expr::trans(bcx, expr); + fn datum_callee<'a>(bcx: &'a Block<'a>, expr: &ast::Expr) -> (&'a Block<'a>, Callee) { + let DatumBlock {mut bcx, datum} = expr::trans(bcx, expr); match ty::get(datum.ty).sty { ty::ty_bare_fn(..) => { - let llval = datum.to_llscalarish(bcx); - return Callee {bcx: bcx, data: Fn(llval)}; + let fn_ty = datum.ty; + (bcx, Fn(pod_value(bcx.tcx(), datum.to_llscalarish(bcx), fn_ty))) } ty::ty_closure(..) => { let datum = unpack_datum!( bcx, datum.to_lvalue_datum(bcx, "callee", expr.id)); - return Callee {bcx: bcx, data: Closure(datum)}; + (bcx, Closure(datum)) } _ => { bcx.tcx().sess.span_bug( @@ -111,33 +94,27 @@ fn trans<'a>(bcx: &'a Block<'a>, expr: &ast::Expr) -> Callee<'a> { } } - fn fn_callee<'a>(bcx: &'a Block<'a>, llfn: ValueRef) -> Callee<'a> { - return Callee {bcx: bcx, data: Fn(llfn)}; - } - fn trans_def<'a>(bcx: &'a Block<'a>, def: ast::Def, ref_expr: &ast::Expr) - -> Callee<'a> { + -> (&'a Block<'a>, Callee) { match def { - ast::DefFn(did, _) | - ast::DefStaticMethod(did, ast::FromImpl(_), _) => { - fn_callee(bcx, trans_fn_ref(bcx, did, ExprId(ref_expr.id))) + ast::DefFn(def_id, _) | + ast::DefStaticMethod(def_id, ast::FromImpl(_), _) | + ast::DefStruct(def_id) => { + (bcx, Fn(trans_fn_ref(bcx, def_id, ExprId(ref_expr.id)))) } ast::DefStaticMethod(impl_did, ast::FromTrait(trait_did), _) => { - fn_callee(bcx, meth::trans_static_method_callee(bcx, impl_did, - trait_did, - ref_expr.id)) + (bcx, Fn(meth::trans_static_method_callee(bcx, impl_did, + trait_did, + ref_expr.id))) } ast::DefVariant(tid, vid, _) => { // nullary variants are not callable assert!(ty::enum_variant_with_id(bcx.tcx(), tid, vid).args.len() > 0u); - fn_callee(bcx, trans_fn_ref(bcx, vid, ExprId(ref_expr.id))) - } - ast::DefStruct(def_id) => { - fn_callee(bcx, trans_fn_ref(bcx, def_id, ExprId(ref_expr.id))) + (bcx, Fn(trans_fn_ref(bcx, vid, ExprId(ref_expr.id)))) } ast::DefStatic(..) | ast::DefArg(..) | @@ -160,7 +137,7 @@ fn trans<'a>(bcx: &'a Block<'a>, expr: &ast::Expr) -> Callee<'a> { } } -pub fn trans_fn_ref(bcx: &Block, def_id: ast::DefId, node: ExprOrMethodCall) -> ValueRef { +pub fn trans_fn_ref(bcx: &Block, def_id: ast::DefId, node: ExprOrMethodCall) -> Datum { /*! * * Translates a reference (with id `ref_id`) to the fn/method @@ -183,17 +160,6 @@ pub fn trans_fn_ref(bcx: &Block, def_id: ast::DefId, node: ExprOrMethodCall) -> vtables) } -fn trans_fn_ref_with_vtables_to_callee<'a>(bcx: &'a Block<'a>, - def_id: ast::DefId, - ref_id: ast::NodeId, - type_params: &[ty::t], - vtables: Option) - -> Callee<'a> { - Callee {bcx: bcx, - data: Fn(trans_fn_ref_with_vtables(bcx, def_id, ExprId(ref_id), - type_params, vtables))} -} - fn resolve_default_method_vtables(bcx: &Block, impl_id: ast::DefId, method: &ty::Method, @@ -243,7 +209,7 @@ pub fn trans_fn_ref_with_vtables( node: ExprOrMethodCall, // node id of use of fn; may be zero if N/A type_params: &[ty::t], // values for fn's ty params vtables: Option) // vtables for the call - -> ValueRef { + -> Datum { /*! * Translates a reference to a fn/method item, monomorphizing and * inlining as it goes. @@ -383,37 +349,22 @@ pub fn trans_fn_ref_with_vtables( MethodCall(_) => None, }; - let (val, must_cast) = - monomorphize::monomorphic_fn(ccx, def_id, &substs, - vtables, self_vtables, - opt_ref_id); - let mut val = val; - if must_cast && node != ExprId(0) { - // Monotype of the REFERENCE to the function (type params - // are subst'd) - let ref_ty = match node { - ExprId(id) => node_id_type(bcx, id), - MethodCall(method_call) => { - let t = bcx.ccx().maps.method_map.borrow().get(&method_call).ty; - monomorphize_type(bcx, t) - } - }; - - val = PointerCast( - bcx, val, type_of::type_of_fn_from_ty(ccx, ref_ty).ptr_to()); - } - return val; + return monomorphize::monomorphic_fn(ccx, def_id, &substs, vtables, + self_vtables, opt_ref_id); } // Find the actual function pointer. - let mut val = { - if def_id.krate == ast::LOCAL_CRATE { - // Internal reference. - get_item_val(ccx, def_id.node) - } else { - // External reference. - trans_external_path(ccx, def_id, fn_tpt.ty) + let datum = if def_id.krate == ast::LOCAL_CRATE { + // Internal reference. + match get_item_val(ccx, def_id.node) { + LvalueDatum(_) => { + ccx.sess().bug("found Lvalue instead of PodValue for fn"); + } + PodValueDatum(datum) => datum } + } else { + // External reference. + trans_external_path(ccx, def_id, fn_tpt.ty) }; // This is subtle and surprising, but sometimes we have to bitcast @@ -439,133 +390,37 @@ pub fn trans_fn_ref_with_vtables( // This can occur on either a crate-local or crate-external // reference. It also occurs when testing libcore and in some // other weird situations. Annoying. - let llty = type_of::type_of_fn_from_ty(ccx, fn_tpt.ty); - let llptrty = llty.ptr_to(); - if val_ty(val) != llptrty { - val = BitCast(bcx, val, llptrty); + if datum.ty != fn_tpt.ty { + let llty = type_of::type_of_fn_from_ty(ccx, fn_tpt.ty); + pod_value(bcx.tcx(), BitCast(bcx, datum.val, llty.ptr_to()), fn_tpt.ty) + } else { + datum } - - val } // ______________________________________________________________________ // Translating calls -pub fn trans_call<'a>( - in_cx: &'a Block<'a>, - call_ex: &ast::Expr, - f: &ast::Expr, - args: CallArgs, - dest: expr::Dest) - -> &'a Block<'a> { - let _icx = push_ctxt("trans_call"); - trans_call_inner(in_cx, - Some(common::expr_info(call_ex)), - expr_ty(in_cx, f), - |cx, _| trans(cx, f), - args, - Some(dest)).bcx -} - -pub fn trans_method_call<'a>( - bcx: &'a Block<'a>, - call_ex: &ast::Expr, - rcvr: &ast::Expr, - args: CallArgs, - dest: expr::Dest) - -> &'a Block<'a> { - let _icx = push_ctxt("trans_method_call"); - debug!("trans_method_call(call_ex={})", call_ex.repr(bcx.tcx())); - let method_call = MethodCall::expr(call_ex.id); - let method_ty = bcx.ccx().maps.method_map.borrow().get(&method_call).ty; - trans_call_inner( - bcx, - Some(common::expr_info(call_ex)), - monomorphize_type(bcx, method_ty), - |cx, arg_cleanup_scope| { - meth::trans_method_callee(cx, method_call, Some(rcvr), arg_cleanup_scope) - }, - args, - Some(dest)).bcx -} - pub fn trans_lang_call<'a>( bcx: &'a Block<'a>, did: ast::DefId, - args: &[ValueRef], + args: &[Datum], dest: Option) -> Result<'a> { - let fty = if did.krate == ast::LOCAL_CRATE { - ty::node_id_to_type(bcx.tcx(), did.node) - } else { - csearch::get_type(bcx.tcx(), did).ty - }; - callee::trans_call_inner(bcx, - None, - fty, - |bcx, _| { - trans_fn_ref_with_vtables_to_callee(bcx, - did, - 0, - [], - None) - }, - ArgVals(args), - dest) -} - -pub fn trans_lang_call_with_type_params<'a>( - bcx: &'a Block<'a>, - did: ast::DefId, - args: &[ValueRef], - type_params: &[ty::t], - dest: expr::Dest) - -> &'a Block<'a> { - let fty; - if did.krate == ast::LOCAL_CRATE { - fty = ty::node_id_to_type(bcx.tcx(), did.node); - } else { - fty = csearch::get_type(bcx.tcx(), did).ty; - } - - return callee::trans_call_inner( - bcx, - None, - fty, - |bcx, _| { - let callee = - trans_fn_ref_with_vtables_to_callee(bcx, did, 0, - type_params, - None); - - let new_llval; - match callee.data { - Fn(llfn) => { - let substituted = ty::subst_tps(callee.bcx.tcx(), - type_params, - None, - fty); - let llfnty = type_of::type_of(callee.bcx.ccx(), - substituted); - new_llval = PointerCast(callee.bcx, llfn, llfnty); - } - _ => fail!() - } - Callee { bcx: callee.bcx, data: Fn(new_llval) } - }, - ArgVals(args), Some(dest)).bcx; + trans_call(bcx, None, + Fn(trans_fn_ref_with_vtables(bcx, did, ExprId(0), [], None)), + args.iter(), |bcx, arg| DatumBlock(bcx, arg.to_expr_datum()), + dest) } -pub fn trans_call_inner<'a>( - bcx: &'a Block<'a>, - call_info: Option, - callee_ty: ty::t, - get_callee: |bcx: &'a Block<'a>, - arg_cleanup_scope: cleanup::ScopeId| - -> Callee<'a>, - args: CallArgs, - dest: Option) - -> Result<'a> { +pub fn trans_call<'a, A, I: Iterator>( + bcx: &'a Block<'a>, + call_info: Option, + callee: Callee, + args: I, + trans_arg: |&'a Block<'a>, A| -> DatumBlock<'a, Expr>, + dest: Option) + -> Result<'a> { /*! * This behemoth of a function translates function calls. * Unfortunately, in order to generate more efficient LLVM @@ -589,36 +444,41 @@ pub fn trans_call_inner<'a>( // cleaned up. If no failure occurs, the values are handed off to // the callee, and hence none of the cleanups in this temporary // scope will ever execute. - let fcx = bcx.fcx; - let ccx = fcx.ccx; - let arg_cleanup_scope = fcx.push_custom_cleanup_scope(); - - let callee = get_callee(bcx, cleanup::CustomScope(arg_cleanup_scope)); - let mut bcx = callee.bcx; + let ccx = bcx.ccx(); + let mut args = args.enumerate(); + let arg_cleanup_scope = bcx.fcx.push_custom_cleanup_scope(); - let (llfn, llenv, llself) = match callee.data { - Fn(llfn) => { - (llfn, None, None) + let (bcx, callee_ty, llfn, llenv_or_self) = match callee { + Fn(callee) => { + (bcx, callee.ty, callee.val, None) } - TraitMethod(d) => { - (d.llfn, None, Some(d.llself)) + TraitMethod(method_ty, method_idx) => { + let (_, self_arg) = args.next().expect("trans_call for TraitMethod missing self"); + let DatumBlock {bcx, datum} = trans_arg(bcx, self_arg); + let (bcx, llfn, llself) = + meth::trans_trait_callee(bcx, + method_ty, + method_idx, + datum, + cleanup::CustomScope(arg_cleanup_scope)); + (bcx, method_ty, llfn, Some(llself)) } - Closure(d) => { + Closure(closure) => { // Closures are represented as (llfn, llclosure) pair: // load the requisite values out. - let pair = d.to_llref(); + let pair = closure.to_llref(); let llfn = GEPi(bcx, pair, [0u, abi::fn_field_code]); let llfn = Load(bcx, llfn); let llenv = GEPi(bcx, pair, [0u, abi::fn_field_box]); let llenv = Load(bcx, llenv); - (llfn, Some(llenv), None) + (bcx, closure.ty, llfn, Some(llenv)) } }; let (abi, ret_ty) = match ty::get(callee_ty).sty { ty::ty_bare_fn(ref f) => (f.abis, f.sig.output), ty::ty_closure(ref f) => (AbiSet::Rust(), f.sig.output), - _ => fail!("expected bare rust fn or closure in trans_call_inner") + _ => fail!("expected bare rust fn or closure in trans_call") }; let is_rust_fn = abi.is_rust() || @@ -636,23 +496,18 @@ pub fn trans_call_inner<'a>( if !type_is_zero_size(ccx, ret_ty) { Some(alloc_ty(bcx, ret_ty, "__llret")) } else { - let llty = type_of::type_of(ccx, ret_ty); - Some(C_undef(llty.ptr_to())) + Some(C_undef(type_of::type_of(ccx, ret_ty).ptr_to())) } } }; - let mut llresult = unsafe { - llvm::LLVMGetUndef(Type::nil(ccx).ptr_to().to_ref()) - }; - // The code below invokes the function, using either the Rust // conventions (if it is a rust fn) or the native conventions // (otherwise). The important part is that, when all is sad // and done, either the return value of the function will have been // written in opt_llretslot (if it is Some) or `llresult` will be // set appropriately (otherwise). - if is_rust_fn { + let (mut bcx, llresult) = if is_rust_fn { let mut llargs = Vec::new(); // Push the out-pointer if we use an out-pointer for this @@ -662,18 +517,21 @@ pub fn trans_call_inner<'a>( } // Push the environment (or a trait object's self). - match (llenv, llself) { - (Some(llenv), None) => llargs.push(llenv), - (None, Some(llself)) => llargs.push(llself), + match llenv_or_self { + Some(llenv_or_self) => llargs.push(llenv_or_self), _ => {} } // Push the arguments. - bcx = trans_args(bcx, args, callee_ty, &mut llargs, - cleanup::CustomScope(arg_cleanup_scope), - llself.is_some()); + let bcx = trans_args(bcx, callee_ty, + cleanup::CustomScope(arg_cleanup_scope), + args, trans_arg, + |arg| { + llargs.push(arg.datum.val); + arg.bcx + }); - fcx.pop_custom_cleanup_scope(arg_cleanup_scope); + bcx.fcx.pop_custom_cleanup_scope(arg_cleanup_scope); // A function pointer is called without the declaration // available, so we have to apply any attributes with ABI @@ -696,13 +554,11 @@ pub fn trans_call_inner<'a>( } // Invoke the actual rust fn and update bcx/llresult. - let (llret, b) = base::invoke(bcx, - llfn, - llargs, - attrs.as_slice(), - call_info); - bcx = b; - llresult = llret; + let (llret, bcx) = base::invoke(bcx, + llfn, + llargs, + attrs.as_slice(), + call_info); // If the Rust convention for this type is return via // the return value, copy it into llretslot. @@ -716,23 +572,32 @@ pub fn trans_call_inner<'a>( } None => {} } + (bcx, llret) } else { // Lang items are the only case where dest is None, and // they are always Rust fns. assert!(dest.is_some()); - let mut llargs = Vec::new(); - let arg_tys = match args { - ArgExprs(a) => a.iter().map(|x| expr_ty(bcx, *x)).collect(), - _ => fail!("expected arg exprs.") + // Also, this can't be a trait object or closure call. + assert!(llenv_or_self.is_none()); + + let mut arg_datums = Vec::new(); + let bcx = trans_args(bcx, callee_ty, + cleanup::CustomScope(arg_cleanup_scope), + args, trans_arg, + |DatumBlock {bcx, datum}| { + arg_datums.push(datum); + bcx + }); + bcx.fcx.pop_custom_cleanup_scope(arg_cleanup_scope); + let bcx = foreign::trans_native_call(bcx, callee_ty, llfn, + opt_llretslot.unwrap(), + arg_datums); + let llresult = unsafe { + llvm::LLVMGetUndef(Type::nil(ccx).ptr_to().to_ref()) }; - bcx = trans_args(bcx, args, callee_ty, &mut llargs, - cleanup::CustomScope(arg_cleanup_scope), false); - fcx.pop_custom_cleanup_scope(arg_cleanup_scope); - bcx = foreign::trans_native_call(bcx, callee_ty, - llfn, opt_llretslot.unwrap(), - llargs.as_slice(), arg_tys); - } + (bcx, llresult) + }; // If the caller doesn't care about the result of this fn call, // drop the temporary slot we made. @@ -754,160 +619,94 @@ pub fn trans_call_inner<'a>( rslt(bcx, llresult) } -pub enum CallArgs<'a> { - // Supply value of arguments as a list of expressions that must be - // translated. This is used in the common case of `foo(bar, qux)`. - ArgExprs(&'a [@ast::Expr]), - - // Supply value of arguments as a list of LLVM value refs; frequently - // used with lang items and so forth, when the argument is an internal - // value. - ArgVals(&'a [ValueRef]), - - // For overloaded operators: `(lhs, Option(rhs, rhs_id))`. `lhs` - // is the left-hand-side and `rhs/rhs_id` is the datum/expr-id of - // the right-hand-side (if any). - ArgOverloadedOp(Datum, Option<(Datum, ast::NodeId)>), -} - -fn trans_args<'a>(cx: &'a Block<'a>, - args: CallArgs, - fn_ty: ty::t, - llargs: &mut Vec , - arg_cleanup_scope: cleanup::ScopeId, - ignore_self: bool) - -> &'a Block<'a> { +// This would be much nicer if it could be an iterator. +fn trans_args<'a, A, I: Iterator<(uint, A)>>( + bcx: &'a Block<'a>, + fn_ty: ty::t, + arg_cleanup_scope: cleanup::ScopeId, + mut args: I, + trans_arg: |&'a Block<'a>, A| -> DatumBlock<'a, Expr>, + each_arg: |DatumBlock<'a, Rvalue>| -> &'a Block<'a>) + -> &'a Block<'a> { let _icx = push_ctxt("trans_args"); + + // Should borrow instead of cloning the arg_tys vector. let arg_tys = ty::ty_fn_args(fn_ty); let variadic = ty::fn_is_variadic(fn_ty); - let mut bcx = cx; + let mut bcx = bcx; // First we figure out the caller's view of the types of the arguments. // This will be needed if this is a generic call, because the callee has // to cast her view of the arguments to the caller's view. - match args { - ArgExprs(arg_exprs) => { - let num_formal_args = arg_tys.len(); - for (i, &arg_expr) in arg_exprs.iter().enumerate() { - if i == 0 && ignore_self { - continue; - } - let arg_ty = if i >= num_formal_args { - assert!(variadic); - expr_ty_adjusted(cx, arg_expr) - } else { - *arg_tys.get(i) - }; - - let arg_datum = unpack_datum!(bcx, expr::trans(bcx, arg_expr)); - llargs.push(unpack_result!(bcx, { - trans_arg_datum(bcx, arg_ty, arg_datum, - arg_cleanup_scope, - DontAutorefArg) - })); - } - } - ArgOverloadedOp(lhs, rhs) => { - assert!(!variadic); - - llargs.push(unpack_result!(bcx, { - trans_arg_datum(bcx, *arg_tys.get(0), lhs, - arg_cleanup_scope, - DontAutorefArg) - })); - - match rhs { - Some((rhs, rhs_id)) => { - assert_eq!(arg_tys.len(), 2); - - llargs.push(unpack_result!(bcx, { - trans_arg_datum(bcx, *arg_tys.get(1), rhs, - arg_cleanup_scope, - DoAutorefArg(rhs_id)) - })); - } - None => assert_eq!(arg_tys.len(), 1) - } - } - ArgVals(vs) => { - llargs.push_all(vs); - } + for (i, arg) in args { + let arg = trans_arg(bcx, arg); + let arg_ty = if i >= arg_tys.len() { + assert!(variadic); + arg.datum.ty + } else { + *arg_tys.get(i) + }; + + bcx = each_arg(trans_arg_datum(arg, arg_ty, arg_cleanup_scope)); } bcx } -pub enum AutorefArg { - DontAutorefArg, - DoAutorefArg(ast::NodeId) -} - -pub fn trans_arg_datum<'a>( - bcx: &'a Block<'a>, - formal_arg_ty: ty::t, - arg_datum: Datum, - arg_cleanup_scope: cleanup::ScopeId, - autoref_arg: AutorefArg) - -> Result<'a> { +pub fn trans_arg_datum<'a>(arg: DatumBlock<'a, Expr>, + formal_arg_ty: ty::t, + arg_cleanup_scope: cleanup::ScopeId) + -> DatumBlock<'a, Rvalue> { let _icx = push_ctxt("trans_arg_datum"); - let mut bcx = bcx; - let ccx = bcx.ccx(); + let ccx = arg.ccx(); debug!("trans_arg_datum({})", - formal_arg_ty.repr(bcx.tcx())); + formal_arg_ty.repr(arg.tcx())); - let arg_datum_ty = arg_datum.ty; + let arg_datum_ty = arg.datum.ty; - debug!(" arg datum: {}", arg_datum.to_str(bcx.ccx())); + debug!(" arg datum: {}", arg.to_str()); - let mut val; - if ty::type_is_bot(arg_datum_ty) { + let (bcx, val, mode) = if ty::type_is_bot(arg_datum_ty) { // For values of type _|_, we generate an // "undef" value, as such a value should never // be inspected. It's important for the value // to have type lldestty (the callee's expected type). - let llformal_arg_ty = type_of::type_of(ccx, formal_arg_ty); + let llformal_arg_ty = type_of::type_of(ccx, formal_arg_ty).to_ref(); unsafe { - val = llvm::LLVMGetUndef(llformal_arg_ty.to_ref()); + (arg.bcx, llvm::LLVMGetUndef(llformal_arg_ty), ByValue) } } else { - // FIXME(#3548) use the adjustments table - match autoref_arg { - DoAutorefArg(arg_id) => { - // We will pass argument by reference - // We want an lvalue, so that we can pass by reference and - let arg_datum = unpack_datum!( - bcx, arg_datum.to_lvalue_datum(bcx, "arg", arg_id)); - val = arg_datum.val; - } - DontAutorefArg => { - // Make this an rvalue, since we are going to be - // passing ownership. - let arg_datum = unpack_datum!( - bcx, arg_datum.to_rvalue_datum(bcx, "arg")); - - // Now that arg_datum is owned, get it into the appropriate - // mode (ref vs value). - let arg_datum = unpack_datum!( - bcx, arg_datum.to_appropriate_datum(bcx)); - - // Technically, ownership of val passes to the callee. - // However, we must cleanup should we fail before the - // callee is actually invoked. - val = arg_datum.add_clean(bcx.fcx, arg_cleanup_scope); - } - } + // Make this an rvalue, since we are going to be + // passing ownership. + let arg = arg.to_rvalue_datumblock("arg"); + + // Now that the argument datum is owned, get it into + // the appropriate mode (ref vs value). + let arg = arg.to_appropriate_datumblock(); + + + // Technically, ownership of val passes to the callee. + // However, we must cleanup should we fail before the + // callee is actually invoked. + let mode = arg.datum.kind.mode; + let bcx = arg.bcx; + let val = arg.datum.add_clean(bcx.fcx, arg_cleanup_scope); if formal_arg_ty != arg_datum_ty { // this could happen due to e.g. subtyping let llformal_arg_ty = type_of::type_of_explicit_arg(ccx, formal_arg_ty); debug!("casting actual type ({}) to match formal ({})", bcx.val_to_str(val), bcx.llty_str(llformal_arg_ty)); - val = PointerCast(bcx, val, llformal_arg_ty); + (bcx, PointerCast(bcx, val, llformal_arg_ty), mode) + } else { + (bcx, val, mode) } - } + }; + + let datum = Datum(val, formal_arg_ty, Rvalue(mode)); - debug!("--- trans_arg_datum passing {}", bcx.val_to_str(val)); - rslt(bcx, val) + debug!("--- trans_arg_datum passing {}", datum.to_str(ccx)); + DatumBlock(bcx, datum) } diff --git a/src/librustc/middle/trans/cleanup.rs b/src/librustc/middle/trans/cleanup.rs index a977ea99ef102..703ae20fc3dbe 100644 --- a/src/librustc/middle/trans/cleanup.rs +++ b/src/librustc/middle/trans/cleanup.rs @@ -666,7 +666,7 @@ impl<'a> CleanupHelperMethods<'a> for FunctionContext<'a> { let llpersonality = callee::trans_fn_ref(pad_bcx, def_id, ExprId(0)); // The only landing pad clause will be 'cleanup' - let llretval = build::LandingPad(pad_bcx, llretty, llpersonality, 1u); + let llretval = build::LandingPad(pad_bcx, llretty, llpersonality.val, 1u); // The landing pad block is a cleanup build::SetCleanup(pad_bcx, llretval); diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs index 78700bab3f24d..0b07ac7518919 100644 --- a/src/librustc/middle/trans/common.rs +++ b/src/librustc/middle/trans/common.rs @@ -711,14 +711,7 @@ pub fn is_null(val: ValueRef) -> bool { // Used to identify cached monomorphized functions and vtables #[deriving(Eq, TotalEq, Hash)] -pub enum mono_param_id { - mono_precise(ty::t, Option<@Vec >), - mono_any, - mono_repr(uint /* size */, - uint /* align */, - MonoDataClass, - datum::RvalueMode), -} +pub struct MonoParamId(ty::t, Option<@Vec>); #[deriving(Eq, TotalEq, Hash)] pub enum MonoDataClass { @@ -745,7 +738,8 @@ pub fn mono_data_classify(t: ty::t) -> MonoDataClass { #[deriving(Eq, TotalEq, Hash)] pub struct mono_id_ { def: ast::DefId, - params: Vec } + params: Vec +} pub type mono_id = @mono_id_; @@ -933,16 +927,6 @@ pub fn dummy_substs(tps: Vec ) -> ty::substs { } } -pub fn filename_and_line_num_from_span(bcx: &Block, span: Span) - -> (ValueRef, ValueRef) { - 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(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(bcx.ccx(), false)) diff --git a/src/librustc/middle/trans/consts.rs b/src/librustc/middle/trans/consts.rs index dc154206e7117..37066aa0c6a7f 100644 --- a/src/librustc/middle/trans/consts.rs +++ b/src/librustc/middle/trans/consts.rs @@ -23,6 +23,7 @@ use middle::trans::base::push_ctxt; use middle::trans::closure; use middle::trans::common::*; use middle::trans::consts; +use middle::trans::datum::*; use middle::trans::expr; use middle::trans::inline; use middle::trans::machine; @@ -618,10 +619,14 @@ fn const_expr_unadjusted(cx: &CrateContext, e: &ast::Expr, Some(ast::DefFn(def_id, _purity)) => { if !ast_util::is_local(def_id) { let ty = csearch::get_type(cx.tcx(), def_id).ty; - (base::trans_external_path(cx, def_id, ty), true) + (base::trans_external_path(cx, def_id, ty).val, true) } else { - assert!(ast_util::is_local(def_id)); - (base::get_item_val(cx, def_id.node), true) + match base::get_item_val(cx, def_id.node) { + LvalueDatum(_) => { + cx.sess().bug("found Lvalue instead of PodValue for fn"); + } + PodValueDatum(datum) => (datum.val, true) + } } } Some(ast::DefStatic(def_id, false)) => { @@ -636,13 +641,9 @@ fn const_expr_unadjusted(cx: &CrateContext, e: &ast::Expr, (adt::trans_const(cx, repr, vinfo.disr_val, []), true) } Some(ast::DefStruct(_)) => { - let ety = ty::expr_ty(cx.tcx(), e); - let llty = type_of::type_of(cx, ety); - (C_null(llty), true) - } - _ => { - cx.sess().span_bug(e.span, "expected a const, fn, struct, or variant def") + (C_null(type_of::type_of(cx, ty::expr_ty(cx.tcx(), e))), true) } + _ => cx.sess().span_bug(e.span, "expected a const, fn, struct, or variant def") } } ast::ExprCall(callee, ref args) => { @@ -680,13 +681,18 @@ fn const_expr_unadjusted(cx: &CrateContext, e: &ast::Expr, pub fn trans_const(ccx: &CrateContext, m: ast::Mutability, id: ast::NodeId) { unsafe { let _icx = push_ctxt("trans_const"); - let g = base::get_item_val(ccx, id); + let llref = match base::get_item_val(ccx, id) { + LvalueDatum(datum) => datum.val, + PodValueDatum(_) => { + ccx.sess().bug("found PodValue instead of Lvalue for static"); + } + }; // At this point, get_item_val has already translated the // constant's initializer to determine its LLVM type. let v = ccx.const_values.borrow().get_copy(&id); - llvm::LLVMSetInitializer(g, v); + llvm::LLVMSetInitializer(llref, v); if m != ast::MutMutable { - llvm::LLVMSetGlobalConstant(g, True); + llvm::LLVMSetGlobalConstant(llref, True); } } } diff --git a/src/librustc/middle/trans/context.rs b/src/librustc/middle/trans/context.rs index c542556c48f99..cfd25e7589197 100644 --- a/src/librustc/middle/trans/context.rs +++ b/src/librustc/middle/trans/context.rs @@ -19,10 +19,11 @@ use middle::astencode; use middle::resolve; use middle::trans::adt; use middle::trans::base; +use middle::trans::base::{decl_crate_map}; use middle::trans::builder::Builder; use middle::trans::common::{C_i32, C_null}; use middle::trans::common::{mono_id,ExternMap,tydesc_info,BuilderRef_res,Stats}; -use middle::trans::base::{decl_crate_map}; +use middle::trans::datum::{Datum, PodValue, LvalueOrPod}; use middle::trans::debuginfo; use middle::trans::type_::Type; use middle::ty; @@ -45,7 +46,7 @@ pub struct CrateContext { tn: TypeNames, externs: RefCell, intrinsics: HashMap<&'static str, ValueRef>, - item_vals: RefCell>, + item_vals: RefCell>, exp_map2: resolve::ExportMap2, reachable: NodeSet, item_symbols: RefCell>, @@ -65,7 +66,7 @@ pub struct CrateContext { // that is generated non_inlineable_statics: RefCell, // Cache instances of monomorphized functions - monomorphized: RefCell>, + monomorphized: RefCell>>, monomorphizing: RefCell>, // Cache generated vtables vtables: RefCell>, diff --git a/src/librustc/middle/trans/controlflow.rs b/src/librustc/middle/trans/controlflow.rs index 8e55319013b82..d95bda58fd13b 100644 --- a/src/librustc/middle/trans/controlflow.rs +++ b/src/librustc/middle/trans/controlflow.rs @@ -15,13 +15,14 @@ use middle::trans::base::*; use middle::trans::build::*; use middle::trans::callee; use middle::trans::common::*; +use middle::trans::datum::*; use middle::trans::debuginfo; use middle::trans::cleanup; use middle::trans::cleanup::CleanupMethods; use middle::trans::expr; -use util::ppaux::Repr; - use middle::trans::type_::Type; +use middle::ty; +use util::ppaux::Repr; use syntax::ast; use syntax::ast::Ident; @@ -325,6 +326,17 @@ pub fn trans_ret<'a>(bcx: &'a Block<'a>, return bcx; } +fn filename_and_line_num_from_span(bcx: &Block, sp: Span) + -> (Datum, Datum) { + let loc = bcx.sess().codemap().lookup_char_pos(sp.lo); + let filename_cstr = C_cstr(bcx.ccx(), + token::intern_and_get_ident(loc.file.deref().name)); + let filename = PointerCast(bcx, filename_cstr, Type::i8p(bcx.ccx())); + let line = C_int(bcx.ccx(), loc.line as int); + (pod_value(bcx.tcx(), filename, ty::mk_imm_ptr(bcx.tcx(), ty::mk_u8())), + pod_value(bcx.tcx(), line, ty::mk_int())) +} + pub fn trans_fail<'a>( bcx: &'a Block<'a>, sp: Span, @@ -333,17 +345,14 @@ pub fn trans_fail<'a>( let ccx = bcx.ccx(); let v_fail_str = C_cstr(ccx, fail_str); let _icx = push_ctxt("trans_fail_value"); - let loc = bcx.sess().codemap().lookup_char_pos(sp.lo); - let v_filename = C_cstr(ccx, token::intern_and_get_ident(loc.file.name)); - let v_line = loc.line as int; + + let (filename, line) = filename_and_line_num_from_span(bcx, sp); let v_str = PointerCast(bcx, v_fail_str, Type::i8p(ccx)); - let v_filename = PointerCast(bcx, v_filename, Type::i8p(ccx)); - let args = vec!(v_str, v_filename, C_int(ccx, v_line)); let did = langcall(bcx, Some(sp), "", FailFnLangItem); - let bcx = callee::trans_lang_call(bcx, - did, - args.as_slice(), - Some(expr::Ignore)).bcx; + let bcx = callee::trans_lang_call(bcx, did, [ + pod_value(bcx.tcx(), v_str, ty::mk_imm_ptr(ccx.tcx(), ty::mk_u8())), + filename, line + ], Some(expr::Ignore)).bcx; Unreachable(bcx); return bcx; } @@ -356,12 +365,12 @@ pub fn trans_fail_bounds_check<'a>( -> &'a Block<'a> { let _icx = push_ctxt("trans_fail_bounds_check"); let (filename, line) = filename_and_line_num_from_span(bcx, sp); - let args = vec!(filename, line, index, len); let did = langcall(bcx, Some(sp), "", FailBoundsCheckFnLangItem); - let bcx = callee::trans_lang_call(bcx, - did, - args.as_slice(), - Some(expr::Ignore)).bcx; + let bcx = callee::trans_lang_call(bcx, did, [ + filename, line, + pod_value(bcx.tcx(), index, ty::mk_int()), + pod_value(bcx.tcx(), len, ty::mk_int()) + ], Some(expr::Ignore)).bcx; Unreachable(bcx); return bcx; } diff --git a/src/librustc/middle/trans/datum.rs b/src/librustc/middle/trans/datum.rs index 4ca2b5a47b05e..762ddeb6dd6e8 100644 --- a/src/librustc/middle/trans/datum.rs +++ b/src/librustc/middle/trans/datum.rs @@ -91,6 +91,27 @@ pub enum RvalueMode { ByValue, } +#[deriving(Clone)] +pub struct PodValue { + // Don't allow constructing the structure outside this module. + priv contents: () +} + +/// A reference to a lvalue or a Pod immediate value. +pub enum LvalueOrPod { + LvalueDatum(Datum), + PodValueDatum(Datum) +} + +impl LvalueOrPod { + pub fn to_expr_datum(self) -> Datum { + match self { + LvalueDatum(l) => l.to_expr_datum(), + PodValueDatum(p) => p.to_expr_datum() + } + } +} + pub fn Datum(val: ValueRef, ty: ty::t, kind: K) -> Datum { Datum { val: val, ty: ty, kind: kind } } @@ -101,6 +122,11 @@ pub fn DatumBlock<'a, K>(bcx: &'a Block<'a>, DatumBlock { bcx: bcx, datum: datum } } +pub fn pod_value(tcx: &ty::ctxt, val: ValueRef, ty: ty::t) -> Datum { + assert!(!ty::type_needs_drop(tcx, ty) && !ty::type_moves_by_default(tcx, ty)); + Datum(val, ty, PodValue { contents: () }) +} + pub fn immediate_rvalue(val: ValueRef, ty: ty::t) -> Datum { return Datum(val, ty, Rvalue(ByValue)); } @@ -271,6 +297,24 @@ impl KindOps for Lvalue { } } +impl KindOps for PodValue { + fn post_store<'a>(&self, + bcx: &'a Block<'a>, + _val: ValueRef, + _ty: ty::t) + -> &'a Block<'a> { + bcx + } + + fn is_by_ref(&self) -> bool { + false + } + + fn to_expr_kind(self) -> Expr { + RvalueExpr(Rvalue(ByValue)) + } +} + impl KindOps for Expr { fn post_store<'a>(&self, bcx: &'a Block<'a>, @@ -687,12 +731,24 @@ impl<'a, K:KindOps> DatumBlock<'a, K> { } } +impl<'a> DatumBlock<'a, Rvalue> { + pub fn to_appropriate_datumblock(self) -> DatumBlock<'a, Rvalue> { + let DatumBlock { bcx, datum } = self; + datum.to_appropriate_datum(bcx) + } +} + impl<'a> DatumBlock<'a, Expr> { pub fn assert_by_ref(self) -> DatumBlock<'a, Expr> { assert!(self.datum.kind.is_by_ref()); self } + pub fn to_rvalue_datumblock(self, name: &'static str) -> DatumBlock<'a, Rvalue> { + let DatumBlock { bcx, datum } = self; + datum.to_rvalue_datum(bcx, name) + } + pub fn store_to(self, dst: ValueRef) -> &'a Block<'a> { let DatumBlock { bcx, datum } = self; datum.store_to(bcx, dst) diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs index 5baf405620646..63045d792cb23 100644 --- a/src/librustc/middle/trans/expr.rs +++ b/src/librustc/middle/trans/expr.rs @@ -191,7 +191,7 @@ fn apply_adjustments<'a>(bcx: &'a Block<'a>, } Some(AutoUnsafe(..)) | // region + unsafe ptrs have same repr Some(AutoPtr(..)) => { - unpack_datum!(bcx, auto_ref(bcx, datum, expr)) + unpack_datum!(bcx, auto_ref(bcx, datum, expr.id)) } Some(AutoBorrowVec(..)) => { unpack_datum!(bcx, auto_slice(bcx, expr, datum)) @@ -294,7 +294,7 @@ fn apply_adjustments<'a>(bcx: &'a Block<'a>, datum: Datum) -> DatumBlock<'a, Expr> { let DatumBlock { bcx, datum } = auto_slice(bcx, expr, datum); - auto_ref(bcx, datum, expr) + auto_ref(bcx, datum, expr.id) } fn auto_borrow_obj<'a>(bcx: &'a Block<'a>, @@ -539,53 +539,44 @@ fn trans_def<'a>(bcx: &'a Block<'a>, ast::DefStatic(did, _) => { let const_ty = expr_ty(bcx, ref_expr); - fn get_did(ccx: &CrateContext, did: ast::DefId) - -> ast::DefId { - if did.krate != ast::LOCAL_CRATE { - inline::maybe_instantiate_inline(ccx, did) - } else { - did - } - } + let did = if did.krate != ast::LOCAL_CRATE { + inline::maybe_instantiate_inline(bcx.ccx(), did) + } else { + did + }; - fn get_val<'a>(bcx: &'a Block<'a>, did: ast::DefId, const_ty: ty::t) - -> ValueRef { - // For external constants, we don't inline. - if did.krate == ast::LOCAL_CRATE { - // The LLVM global has the type of its initializer, - // which may not be equal to the enum's type for - // non-C-like enums. - let val = base::get_item_val(bcx.ccx(), did.node); - let pty = type_of::type_of(bcx.ccx(), const_ty).ptr_to(); - PointerCast(bcx, val, pty) - } else { - match bcx.ccx().extern_const_values.borrow().find(&did) { - None => {} // Continue. - Some(llval) => { - return *llval; - } + // For external constants, we don't inline. + if did.krate == ast::LOCAL_CRATE { + // The LLVM global has the type of its initializer, + // which may not be equal to the enum's type for + // non-C-like enums. + let llref = match get_item_val(bcx.ccx(), did.node) { + LvalueDatum(datum) => datum.val, + PodValueDatum(_) => { + bcx.sess().bug("found PodValue instead of Lvalue for static"); } - - unsafe { - let llty = type_of::type_of(bcx.ccx(), const_ty); - let symbol = csearch::get_symbol( - &bcx.ccx().sess().cstore, - did); - let llval = symbol.with_c_str(|buf| { - llvm::LLVMAddGlobal(bcx.ccx().llmod, - llty.to_ref(), - buf) - }); - bcx.ccx().extern_const_values.borrow_mut() - .insert(did, llval); - llval + }; + let pty = type_of::type_of(bcx.ccx(), const_ty).ptr_to(); + let llref = PointerCast(bcx, llref, pty); + DatumBlock(bcx, Datum(llref, const_ty, LvalueExpr)) + } else { + match bcx.ccx().extern_const_values.borrow().find(&did) { + None => {} // Continue. + Some(&llval) => { + return DatumBlock(bcx, Datum(llval, const_ty, LvalueExpr)); } } - } - let did = get_did(bcx.ccx(), did); - let val = get_val(bcx, did, const_ty); - DatumBlock(bcx, Datum(val, const_ty, LvalueExpr)) + unsafe { + let llty = type_of::type_of(bcx.ccx(), const_ty); + let symbol = csearch::get_symbol(&bcx.sess().cstore, did); + let llval = symbol.with_c_str(|buf| { + llvm::LLVMAddGlobal(bcx.ccx().llmod, llty.to_ref(), buf) + }); + bcx.ccx().extern_const_values.borrow_mut().insert(did, llval); + DatumBlock(bcx, Datum(llval, const_ty, LvalueExpr)) + } + } } _ => { DatumBlock(bcx, trans_local_var(bcx, def).to_expr_datum()) @@ -738,14 +729,23 @@ fn trans_rvalue_dps_unadjusted<'a>(bcx: &'a Block<'a>, closure::trans_expr_fn(bcx, sigil, decl, body, expr.id, dest) } ast::ExprCall(f, ref args) => { - callee::trans_call(bcx, expr, f, callee::ArgExprs(args.as_slice()), dest) + let (bcx, callee) = callee::trans(bcx, f); + callee::trans_call(bcx, + Some(expr_info(expr)), + callee, + args.iter(), + |bcx, &arg| trans(bcx, arg), + Some(dest)).bcx } ast::ExprMethodCall(_, _, ref args) => { - callee::trans_method_call(bcx, - expr, - *args.get(0), - callee::ArgExprs(args.as_slice()), - dest) + let method_call = MethodCall::expr(expr.id); + callee::trans_call( + bcx, + Some(expr_info(expr)), + meth::trans_method_callee(bcx, method_call), + args.iter(), + |bcx, &arg| trans(bcx, arg), + Some(dest)).bcx } ast::ExprBinary(_, lhs, rhs) => { // if not overloaded, would be RvalueDatumExpr @@ -815,9 +815,8 @@ fn trans_def_dps_unadjusted<'a>( let variant_info = ty::enum_variant_with_id(bcx.tcx(), tid, vid); if variant_info.args.len() > 0u { // N-ary variant. - let llfn = callee::trans_fn_ref(bcx, vid, ExprId(ref_expr.id)); - Store(bcx, llfn, lldest); - return bcx; + let callee = callee::trans_fn_ref(bcx, vid, ExprId(ref_expr.id)); + callee.store_to(bcx, lldest) } else { // Nullary variant. let ty = expr_ty(bcx, ref_expr); @@ -851,15 +850,14 @@ fn trans_def_fn_unadjusted<'a>(bcx: &'a Block<'a>, def: ast::Def) -> DatumBlock<'a, Expr> { let _icx = push_ctxt("trans_def_datum_unadjusted"); - let llfn = match def { + DatumBlock(bcx, match def { ast::DefFn(did, _) | ast::DefStruct(did) | ast::DefVariant(_, did, _) | ast::DefStaticMethod(did, ast::FromImpl(_), _) => { callee::trans_fn_ref(bcx, did, ExprId(ref_expr.id)) } ast::DefStaticMethod(impl_did, ast::FromTrait(trait_did), _) => { - meth::trans_static_method_callee(bcx, impl_did, - trait_did, ref_expr.id) + meth::trans_static_method_callee(bcx, impl_did, trait_did, ref_expr.id) } _ => { bcx.tcx().sess.span_bug(ref_expr.span, format!( @@ -867,10 +865,7 @@ fn trans_def_fn_unadjusted<'a>(bcx: &'a Block<'a>, def, ref_expr.repr(bcx.tcx()))); } - }; - - let fn_ty = expr_ty(bcx, ref_expr); - DatumBlock(bcx, Datum(llfn, fn_ty, RvalueExpr(Rvalue(ByValue)))) + }).to_expr_datumblock() } pub fn trans_local_var<'a>(bcx: &'a Block<'a>, @@ -1451,7 +1446,7 @@ fn trans_binary<'a>(bcx: &'a Block<'a>, } } -fn trans_overloaded_op<'a, 'b>( +fn trans_overloaded_op<'a>( bcx: &'a Block<'a>, expr: &ast::Expr, method_call: MethodCall, @@ -1459,18 +1454,21 @@ fn trans_overloaded_op<'a, 'b>( rhs: Option<(Datum, ast::NodeId)>, dest: Option) -> Result<'a> { - let method_ty = bcx.ccx().maps.method_map.borrow().get(&method_call).ty; - callee::trans_call_inner(bcx, - Some(expr_info(expr)), - monomorphize_type(bcx, method_ty), - |bcx, arg_cleanup_scope| { - meth::trans_method_callee(bcx, - method_call, - None, - arg_cleanup_scope) - }, - callee::ArgOverloadedOp(lhs, rhs), - dest) + let mut bcx = bcx; + let rhs = match rhs { + Some((rhs_datum, rhs_id)) => { + // FIXME(#3548) use the adjustments table + Some(unpack_datum!(bcx, auto_ref(bcx, rhs_datum, rhs_id))) + } + None => None + }; + + callee::trans_call(bcx, + Some(expr_info(expr)), + meth::trans_method_callee(bcx, method_call), + Some(lhs).move_iter().chain(rhs.move_iter()), + |bcx, arg_datum| DatumBlock(bcx, arg_datum), + dest) } fn int_cast(bcx: &Block, @@ -1649,13 +1647,13 @@ fn trans_assign_op<'a>( fn auto_ref<'a>(bcx: &'a Block<'a>, datum: Datum, - expr: &ast::Expr) + expr_id: ast::NodeId) -> DatumBlock<'a, Expr> { let mut bcx = bcx; // Ensure cleanup of `datum` if not already scheduled and obtain // a "by ref" pointer. - let lv_datum = unpack_datum!(bcx, datum.to_lvalue_datum(bcx, "autoref", expr.id)); + let lv_datum = unpack_datum!(bcx, datum.to_lvalue_datum(bcx, "autoref", expr_id)); // Compute final type. Note that we are loose with the region and // mutability, since those things don't matter in trans. @@ -1718,7 +1716,7 @@ fn deref_once<'a>(bcx: &'a Block<'a>, datum } else { // Always perform an AutoPtr when applying an overloaded auto-deref. - unpack_datum!(bcx, auto_ref(bcx, datum, expr)) + unpack_datum!(bcx, auto_ref(bcx, datum, expr.id)) }; let val = unpack_result!(bcx, trans_overloaded_op(bcx, expr, method_call, datum, None, None)); diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs index 3fd677b34d984..06ee4f0db2339 100644 --- a/src/librustc/middle/trans/foreign.rs +++ b/src/librustc/middle/trans/foreign.rs @@ -19,6 +19,7 @@ use middle::trans::build::*; use middle::trans::builder::noname; use middle::trans::cabi; use middle::trans::common::*; +use middle::trans::datum::*; use middle::trans::machine; use middle::trans::type_::Type; use middle::trans::type_of::*; @@ -32,8 +33,7 @@ use syntax::abi::{RustIntrinsic, Rust, Stdcall, Fastcall, System}; use syntax::codemap::Span; use syntax::parse::token::{InternedString, special_idents}; use syntax::parse::token; -use syntax::{ast}; -use syntax::{attr, ast_map}; +use syntax::{ast, attr, ast_map}; use util::ppaux::{Repr, UserString}; /////////////////////////////////////////////////////////////////////////// @@ -255,8 +255,7 @@ pub fn trans_native_call<'a>( callee_ty: ty::t, llfn: ValueRef, llretptr: ValueRef, - llargs_rust: &[ValueRef], - passed_arg_tys: Vec ) + arg_datums: Vec>) -> &'a Block<'a> { /*! * Prepares a call to a native function. This requires adapting @@ -267,14 +266,14 @@ pub fn trans_native_call<'a>( * - `callee_ty`: Rust type for the function we are calling * - `llfn`: the function pointer we are calling * - `llretptr`: where to store the return value of the function - * - `llargs_rust`: a list of the argument values, prepared - * as they would be if calling a Rust function - * - `passed_arg_tys`: Rust type for the arguments. Normally we - * can derive these from callee_ty but in the case of variadic - * functions passed_arg_tys will include the Rust type of all - * the arguments including the ones not specified in the fn's signature. + * - `arg_datums`: a list of the argument datums, prepared as + * they would be if calling a Rust function. Note that in the + * case of variadic functions, the datums' types will include + * the Rust type of all the arguments including the ones not + * specified in the fn's signature. */ + let mut bcx = bcx; let ccx = bcx.ccx(); let tcx = bcx.tcx(); @@ -289,14 +288,14 @@ pub fn trans_native_call<'a>( ty::ty_bare_fn(ref fn_ty) => (fn_ty.abis, fn_ty.sig.clone()), _ => ccx.sess().bug("trans_native_call called on non-function type") }; - let llsig = foreign_signature(ccx, &fn_sig, passed_arg_tys.as_slice()); + let llsig = foreign_signature(ccx, &fn_sig, arg_datums.iter().map(|arg| arg.ty)); let ret_def = !return_type_is_void(bcx.ccx(), fn_sig.output); let fn_type = cabi::compute_abi_info(ccx, llsig.llarg_tys.as_slice(), llsig.llret_ty, ret_def); - let arg_tys: &[cabi::ArgType] = fn_type.arg_tys.as_slice(); + let arg_tys = fn_type.arg_tys.as_slice(); let mut llargs_foreign = Vec::new(); @@ -317,42 +316,23 @@ pub fn trans_native_call<'a>( } } - for (i, &llarg_rust) in llargs_rust.iter().enumerate() { - let mut llarg_rust = llarg_rust; - + for (i, arg_datum) in arg_datums.move_iter().enumerate() { if arg_tys[i].is_ignore() { continue; } - // Does Rust pass this argument by pointer? - let rust_indirect = type_of::arg_is_indirect(ccx, - *passed_arg_tys.get(i)); - - debug!("argument {}, llarg_rust={}, rust_indirect={}, arg_ty={}", - i, - ccx.tn.val_to_str(llarg_rust), - rust_indirect, - ccx.tn.type_to_str(arg_tys[i].ty)); + debug!("argument {}: {}", i, arg_datum.to_str(ccx)); // Ensure that we always have the Rust value indirectly, // because it makes bitcasting easier. - if !rust_indirect { - let scratch = - base::alloca(bcx, - type_of::type_of(ccx, *passed_arg_tys.get(i)), - "__arg"); - Store(bcx, llarg_rust, scratch); - llarg_rust = scratch; - } - - debug!("llarg_rust={} (after indirection)", - ccx.tn.val_to_str(llarg_rust)); + let arg_datum = unpack_datum!(bcx, arg_datum.to_ref_datum(bcx)); + debug!("arg_datum={} (after indirection)", arg_datum.to_str(ccx)); // Check whether we need to do any casting - match arg_tys[i].cast { - Some(ty) => llarg_rust = BitCast(bcx, llarg_rust, ty.ptr_to()), - None => () - } + let llarg_rust = match arg_tys[i].cast { + Some(ty) => BitCast(bcx, arg_datum.val, ty.ptr_to()), + None => arg_datum.val + }; debug!("llarg_rust={} (after casting)", ccx.tn.val_to_str(llarg_rust)); @@ -500,7 +480,7 @@ pub fn register_rust_fn_with_foreign_abi(ccx: &CrateContext, sp: Span, sym: ~str, node_id: ast::NodeId) - -> ValueRef { + -> Datum { let _icx = push_ctxt("foreign::register_foreign_fn"); let tys = foreign_types_for_id(ccx, node_id); @@ -517,7 +497,7 @@ pub fn register_rust_fn_with_foreign_abi(ccx: &CrateContext, add_argument_attributes(&tys, llfn); debug!("register_rust_fn_with_foreign_abi(node_id={:?}, llfn_ty={}, llfn={})", node_id, ccx.tn.type_to_str(llfn_ty), ccx.tn.val_to_str(llfn)); - llfn + pod_value(ccx.tcx(), llfn, t) } pub fn trans_rust_fn_with_foreign_abi(ccx: &CrateContext, @@ -829,8 +809,10 @@ pub fn link_name(i: &ast::ForeignItem) -> InternedString { } } -fn foreign_signature(ccx: &CrateContext, fn_sig: &ty::FnSig, arg_tys: &[ty::t]) - -> LlvmSignature { +fn foreign_signature>(ccx: &CrateContext, + fn_sig: &ty::FnSig, + arg_tys: I) + -> LlvmSignature { /*! * The ForeignSignature is the LLVM types of the arguments/return type * of a function. Note that these LLVM types are not quite the same @@ -839,11 +821,9 @@ fn foreign_signature(ccx: &CrateContext, fn_sig: &ty::FnSig, arg_tys: &[ty::t]) * values by pointer like we do. */ - let llarg_tys = arg_tys.iter().map(|&arg| type_of(ccx, arg)).collect(); - let llret_ty = type_of::type_of(ccx, fn_sig.output); LlvmSignature { - llarg_tys: llarg_tys, - llret_ty: llret_ty, + llarg_tys: arg_tys.map(|arg| type_of(ccx, arg)).collect(), + llret_ty: type_of::type_of(ccx, fn_sig.output), sret: type_of::return_uses_outptr(ccx, fn_sig.output), } } @@ -859,7 +839,7 @@ fn foreign_types_for_fn_ty(ccx: &CrateContext, ty::ty_bare_fn(ref fn_ty) => fn_ty.sig.clone(), _ => ccx.sess().bug("foreign_types_for_fn_ty called on non-function type") }; - let llsig = foreign_signature(ccx, &fn_sig, fn_sig.inputs.as_slice()); + let llsig = foreign_signature(ccx, &fn_sig, fn_sig.inputs.iter().map(|arg| *arg)); let ret_def = !return_type_is_void(ccx, fn_sig.output); let fn_ty = cabi::compute_abi_info(ccx, llsig.llarg_tys.as_slice(), diff --git a/src/librustc/middle/trans/glue.rs b/src/librustc/middle/trans/glue.rs index da9d06b9a7526..fabe4c0fc49cb 100644 --- a/src/librustc/middle/trans/glue.rs +++ b/src/librustc/middle/trans/glue.rs @@ -25,6 +25,7 @@ use middle::trans::callee; use middle::trans::cleanup; use middle::trans::cleanup::CleanupMethods; use middle::trans::common::*; +use middle::trans::datum::*; use middle::trans::expr; use middle::trans::machine::*; use middle::trans::reflect; @@ -44,18 +45,20 @@ use syntax::parse::token; pub fn trans_free<'a>(cx: &'a Block<'a>, v: ValueRef) -> &'a Block<'a> { let _icx = push_ctxt("trans_free"); + let ptr = PointerCast(cx, v, Type::i8p(cx.ccx())); callee::trans_lang_call(cx, langcall(cx, None, "", FreeFnLangItem), - [PointerCast(cx, v, Type::i8p(cx.ccx()))], + [pod_value(cx.tcx(), ptr, ty::mk_imm_ptr(cx.tcx(), ty::mk_u8()))], Some(expr::Ignore)).bcx } pub fn trans_exchange_free<'a>(cx: &'a Block<'a>, v: ValueRef) -> &'a Block<'a> { let _icx = push_ctxt("trans_exchange_free"); + let ptr = PointerCast(cx, v, Type::i8p(cx.ccx())); callee::trans_lang_call(cx, langcall(cx, None, "", ExchangeFreeFnLangItem), - [PointerCast(cx, v, Type::i8p(cx.ccx()))], + [pod_value(cx.tcx(), ptr, ty::mk_imm_ptr(cx.tcx(), ty::mk_u8()))], Some(expr::Ignore)).bcx } @@ -210,7 +213,8 @@ fn make_visit_glue<'a>(bcx: &'a Block<'a>, v: ValueRef, t: ty::t) } }; let v = PointerCast(bcx, v, type_of(bcx.ccx(), object_ty).ptr_to()); - bcx = reflect::emit_calls_to_trait_visit_ty(bcx, t, v, visitor_trait.def_id); + let visitor = Datum(v, object_ty, Lvalue); + bcx = reflect::emit_calls_to_trait_visit_ty(bcx, t, visitor, visitor_trait.def_id); bcx } diff --git a/src/librustc/middle/trans/inline.rs b/src/librustc/middle/trans/inline.rs index b96d71366e003..bd71f5d4908af 100644 --- a/src/librustc/middle/trans/inline.rs +++ b/src/librustc/middle/trans/inline.rs @@ -13,6 +13,7 @@ use metadata::csearch; use middle::astencode; use middle::trans::base::{push_ctxt, trans_item, get_item_val, trans_fn}; use middle::trans::common::*; +use middle::trans::datum::*; use middle::ty; use syntax::ast; @@ -63,12 +64,17 @@ pub fn maybe_instantiate_inline(ccx: &CrateContext, fn_id: ast::DefId) // provides match item.node { ast::ItemStatic(..) => { - let g = get_item_val(ccx, item.id); + let llref = match get_item_val(ccx, item.id) { + LvalueDatum(datum) => datum.val, + PodValueDatum(_) => { + ccx.sess().bug("found PodValue instead of Lvalue for static"); + } + }; // see the comment in get_item_val() as to why this check is // performed here. if !attr::contains_name(item.attrs.as_slice(), "address_insignificant") { - SetLinkage(g, AvailableExternallyLinkage); + SetLinkage(llref, AvailableExternallyLinkage); } } _ => {} @@ -130,7 +136,12 @@ pub fn maybe_instantiate_inline(ccx: &CrateContext, fn_id: ast::DefId) mth.generics.ty_params.len(); if num_type_params == 0 { - let llfn = get_item_val(ccx, mth.id); + let llfn = match get_item_val(ccx, mth.id) { + LvalueDatum(_) => { + ccx.sess().bug("found Lvalue instead of PodValue for method"); + } + PodValueDatum(datum) => datum.val + }; trans_fn(ccx, mth.decl, mth.body, llfn, None, mth.id, []); } local_def(mth.id) diff --git a/src/librustc/middle/trans/meth.rs b/src/librustc/middle/trans/meth.rs index 4701f38c09a8b..e952ecaa960da 100644 --- a/src/librustc/middle/trans/meth.rs +++ b/src/librustc/middle/trans/meth.rs @@ -65,7 +65,12 @@ pub fn trans_impl(ccx: &CrateContext, } for method in methods.iter() { if method.generics.ty_params.len() == 0u { - let llfn = get_item_val(ccx, method.id); + let llfn = match get_item_val(ccx, method.id) { + LvalueDatum(_) => { + ccx.sess().bug("found Lvalue instead of PodValue for method"); + } + PodValueDatum(datum) => datum.val + }; trans_fn(ccx, method.decl, method.body, llfn, None, method.id, []); } else { @@ -75,28 +80,7 @@ pub fn trans_impl(ccx: &CrateContext, } } -/// Translates a (possibly monomorphized) method body. -/// -/// Parameters: -/// * `method`: the AST node for the method -/// * `param_substs`: if this is a generic method, the current values for -/// type parameters and so forth, else None -/// * `llfn`: the LLVM ValueRef for the method -/// -pub fn trans_method(ccx: &CrateContext, method: &ast::Method, - param_substs: Option<@param_substs>, - llfn: ValueRef) -> ValueRef { - trans_fn(ccx, method.decl, method.body, - llfn, param_substs, method.id, []); - llfn -} - -pub fn trans_method_callee<'a>( - bcx: &'a Block<'a>, - method_call: MethodCall, - self_expr: Option<&ast::Expr>, - arg_cleanup_scope: cleanup::ScopeId) - -> Callee<'a> { +pub fn trans_method_callee(bcx: &Block, method_call: MethodCall) -> Callee { let _icx = push_ctxt("meth::trans_method_callee"); let (origin, method_ty) = match bcx.ccx().maps.method_map @@ -114,10 +98,7 @@ pub fn trans_method_callee<'a>( match origin { typeck::MethodStatic(did) => { - Callee { - bcx: bcx, - data: Fn(callee::trans_fn_ref(bcx, did, MethodCall(method_call))) - } + Fn(callee::trans_fn_ref(bcx, did, MethodCall(method_call))) } typeck::MethodParam(typeck::MethodParam { trait_id: trait_id, @@ -131,29 +112,16 @@ pub fn trans_method_callee<'a>( bcx.tcx(), trait_id); - let vtbl = find_vtable(bcx.tcx(), substs, p, b); trans_monomorphized_callee(bcx, method_call, - trait_id, off, vtbl) + trait_id, off, + find_vtable(bcx.tcx(), substs, p, b)) } // how to get rid of this? None => fail!("trans_method_callee: missing param_substs") } } - typeck::MethodObject(ref mt) => { - let self_expr = match self_expr { - Some(self_expr) => self_expr, - None => { - bcx.sess().span_bug(bcx.tcx().map.span(method_call.expr_id), - "self expr wasn't provided for trait object \ - callee (trying to call overloaded op?)") - } - }; - trans_trait_callee(bcx, - monomorphize_type(bcx, method_ty), - mt.real_index, - self_expr, - arg_cleanup_scope) + TraitMethod(monomorphize_type(bcx, method_ty), mt.real_index) } } } @@ -162,7 +130,7 @@ pub fn trans_static_method_callee(bcx: &Block, method_id: ast::DefId, trait_id: ast::DefId, expr_id: ast::NodeId) - -> ValueRef { + -> Datum { let _icx = push_ctxt("meth::trans_static_method_callee"); let ccx = bcx.ccx(); @@ -222,13 +190,13 @@ pub fn trans_static_method_callee(bcx: &Block, bcx, mth_id, ExprId(expr_id), rcvr_substs.as_slice(), rcvr_origins); - let llfn = trans_fn_ref_with_vtables(bcx, mth_id, ExprId(expr_id), - callee_substs.as_slice(), - Some(callee_origins)); + let callee = trans_fn_ref_with_vtables(bcx, mth_id, ExprId(expr_id), + callee_substs.as_slice(), + Some(callee_origins)); let callee_ty = node_id_type(bcx, expr_id); let llty = type_of_fn_from_ty(ccx, callee_ty).ptr_to(); - PointerCast(bcx, llfn, llty) + pod_value(bcx.tcx(), PointerCast(bcx, callee.val, llty), callee_ty) } _ => { fail!("vtable_param left in monomorphized \ @@ -255,12 +223,12 @@ pub fn method_with_name(ccx: &CrateContext, meth.def_id } -fn trans_monomorphized_callee<'a>(bcx: &'a Block<'a>, - method_call: MethodCall, - trait_id: ast::DefId, - n_method: uint, - vtbl: typeck::vtable_origin) - -> Callee<'a> { +fn trans_monomorphized_callee(bcx: &Block, + method_call: MethodCall, + trait_id: ast::DefId, + n_method: uint, + vtbl: typeck::vtable_origin) + -> Callee { let _icx = push_ctxt("meth::trans_monomorphized_callee"); match vtbl { typeck::vtable_static(impl_did, ref rcvr_substs, rcvr_origins) => { @@ -276,13 +244,11 @@ fn trans_monomorphized_callee<'a>(bcx: &'a Block<'a>, rcvr_substs.as_slice(), rcvr_origins); // translate the function - let llfn = trans_fn_ref_with_vtables(bcx, - mth_id, - MethodCall(method_call), - callee_substs.as_slice(), - Some(callee_origins)); - - Callee { bcx: bcx, data: Fn(llfn) } + Fn(trans_fn_ref_with_vtables(bcx, + mth_id, + MethodCall(method_call), + callee_substs.as_slice(), + Some(callee_origins))) } typeck::vtable_param(..) => { fail!("vtable_param left in monomorphized function's vtable substs"); @@ -344,12 +310,12 @@ fn combine_impl_and_methods_tps(bcx: &Block, (ty_substs, vtables) } -fn trans_trait_callee<'a>(bcx: &'a Block<'a>, - method_ty: ty::t, - n_method: uint, - self_expr: &ast::Expr, - arg_cleanup_scope: cleanup::ScopeId) - -> Callee<'a> { +pub fn trans_trait_callee<'a>(bcx: &'a Block<'a>, + method_ty: ty::t, + n_method: uint, + self_datum: Datum, + arg_cleanup_scope: cleanup::ScopeId) + -> (&'a Block<'a>, ValueRef, ValueRef) { /*! * Create a method callee where the method is coming from a trait * object (e.g., ~Trait type). In this case, we must pull the fn @@ -361,18 +327,14 @@ fn trans_trait_callee<'a>(bcx: &'a Block<'a>, let _icx = push_ctxt("meth::trans_trait_callee"); let mut bcx = bcx; + let ccx = bcx.ccx(); - // Translate self_datum and take ownership of the value by - // converting to an rvalue. - let self_datum = unpack_datum!( - bcx, expr::trans(bcx, self_expr)); - - let llval = if ty::type_needs_drop(bcx.tcx(), self_datum.ty) { + let llpair = if ty::type_needs_drop(bcx.tcx(), self_datum.ty) { + // Take ownership of self by converting to an rvalue. let self_datum = unpack_datum!( bcx, self_datum.to_rvalue_datum(bcx, "trait_callee")); - // Convert to by-ref since `trans_trait_callee_from_llval` wants it - // that way. + // Convert to by-ref to extract the fields. let self_datum = unpack_datum!( bcx, self_datum.to_ref_datum(bcx)); @@ -385,22 +347,6 @@ fn trans_trait_callee<'a>(bcx: &'a Block<'a>, self_datum.val }; - trans_trait_callee_from_llval(bcx, method_ty, n_method, llval) -} - -pub fn trans_trait_callee_from_llval<'a>(bcx: &'a Block<'a>, - callee_ty: ty::t, - n_method: uint, - llpair: ValueRef) - -> Callee<'a> { - /*! - * Same as `trans_trait_callee()` above, except that it is given - * a by-ref pointer to the object pair. - */ - - let _icx = push_ctxt("meth::trans_trait_callee"); - let ccx = bcx.ccx(); - // Load the data pointer from the object. debug!("(translating trait callee) loading second index from pair"); let llboxptr = GEPi(bcx, llpair, [0u, abi::trt_field_box]); @@ -410,13 +356,11 @@ pub fn trans_trait_callee_from_llval<'a>(bcx: &'a Block<'a>, // Load the function from the vtable and cast it to the expected type. debug!("(translating trait callee) loading method"); // Replace the self type (&Self or ~Self) with an opaque pointer. - let llcallee_ty = match ty::get(callee_ty).sty { + let llcallee_ty = match ty::get(method_ty).sty { ty::ty_bare_fn(ref f) if f.abis.is_rust() => { type_of_rust_fn(ccx, true, f.sig.inputs.slice_from(1), f.sig.output) } - _ => { - ccx.sess().bug("meth::trans_trait_callee given non-bare-rust-fn"); - } + _ => ccx.sess().bug("meth::trans_trait_callee given non-bare-rust-fn") }; let llvtable = Load(bcx, PointerCast(bcx, @@ -426,13 +370,7 @@ pub fn trans_trait_callee_from_llval<'a>(bcx: &'a Block<'a>, let mptr = Load(bcx, GEPi(bcx, llvtable, [0u, n_method + 1])); let mptr = PointerCast(bcx, mptr, llcallee_ty.ptr_to()); - return Callee { - bcx: bcx, - data: TraitMethod(MethodData { - llfn: mptr, - llself: llself, - }) - }; + (bcx, mptr, llself) } pub fn vtable_id(ccx: &CrateContext, @@ -556,7 +494,7 @@ fn emit_vtable_methods(bcx: &Block, token::get_ident(ident)); C_null(Type::nil(ccx).ptr_to()) } else { - trans_fn_ref_with_vtables(bcx, m_id, ExprId(0), substs, Some(vtables)) + trans_fn_ref_with_vtables(bcx, m_id, ExprId(0), substs, Some(vtables)).val } }) } diff --git a/src/librustc/middle/trans/monomorphize.rs b/src/librustc/middle/trans/monomorphize.rs index 80a7fe2facfeb..41fe3f7cb7a55 100644 --- a/src/librustc/middle/trans/monomorphize.rs +++ b/src/librustc/middle/trans/monomorphize.rs @@ -11,12 +11,12 @@ use back::link::mangle_exported_name; use driver::session; -use lib::llvm::ValueRef; use middle::trans::base::{set_llvm_fn_attrs, set_inline_hint}; use middle::trans::base::{trans_enum_variant, push_ctxt, get_item_val}; use middle::trans::base::{trans_fn, decl_internal_rust_fn}; use middle::trans::base; use middle::trans::common::*; +use middle::trans::datum::*; use middle::trans::meth; use middle::trans::intrinsic; use middle::ty; @@ -33,7 +33,7 @@ pub fn monomorphic_fn(ccx: &CrateContext, vtables: Option, self_vtables: Option, ref_id: Option) - -> (ValueRef, bool) { + -> Datum { debug!("monomorphic_fn(\ fn_id={}, \ real_substs={}, \ @@ -48,7 +48,6 @@ pub fn monomorphic_fn(ccx: &CrateContext, assert!(real_substs.tps.iter().all(|t| !ty::type_needs_infer(*t))); let _icx = push_ctxt("monomorphic_fn"); - let mut must_cast = false; let psubsts = @param_substs { tys: real_substs.tps.clone(), @@ -61,10 +60,6 @@ pub fn monomorphic_fn(ccx: &CrateContext, for s in psubsts.tys.iter() { assert!(!ty::type_has_params(*s)); } let hash_id = make_mono_id(ccx, fn_id, &*psubsts); - if hash_id.params.iter().any( - |p| match *p { mono_precise(_, _) => false, _ => true }) { - must_cast = true; - } debug!("monomorphic_fn(\ fn_id={}, \ @@ -75,12 +70,12 @@ pub fn monomorphic_fn(ccx: &CrateContext, hash_id); match ccx.monomorphized.borrow().find(&hash_id) { - Some(&val) => { + Some(&datum) => { debug!("leaving monomorphic fn {}", - ty::item_path_str(ccx.tcx(), fn_id)); - return (val, must_cast); + ty::item_path_str(ccx.tcx(), fn_id)); + return datum; } - None => () + None => {} } let tpt = ty::lookup_item_type(ccx.tcx(), fn_id); @@ -101,7 +96,12 @@ pub fn monomorphic_fn(ccx: &CrateContext, ast_map::NodeForeignItem(_) => { if !ccx.tcx.map.get_foreign_abis(fn_id.node).is_intrinsic() { // Foreign externs don't have to be monomorphized. - return (get_item_val(ccx, fn_id.node), true); + match get_item_val(ccx, fn_id.node) { + LvalueDatum(_) => { + ccx.sess().bug("found Lvalue instead of PodValue for extern fn"); + } + PodValueDatum(datum) => return datum + } } } ast_map::NodeTraitMethod(method) => { @@ -158,61 +158,55 @@ pub fn monomorphic_fn(ccx: &CrateContext, ccx.stats.n_monos.set(ccx.stats.n_monos.get() + 1); - let depth; - { - let mut monomorphizing = ccx.monomorphizing.borrow_mut(); - depth = match monomorphizing.find(&fn_id) { - Some(&d) => d, None => 0 - }; + let depth = *ccx.monomorphizing.borrow().find(&fn_id).unwrap_or(&0); - // Random cut-off -- code that needs to instantiate the same function - // recursively more than thirty times can probably safely be assumed - // to be causing an infinite expansion. - if depth > ccx.sess().recursion_limit.get() { - ccx.sess().span_fatal(ccx.tcx.map.span(fn_id.node), - "reached the recursion limit during monomorphization"); - } - - monomorphizing.insert(fn_id, depth + 1); + // Random cut-off -- code that needs to instantiate the same function + // recursively more than thirty times can probably safely be assumed + // to be causing an infinite expansion. + if depth > ccx.sess().recursion_limit.get() { + ccx.sess().span_fatal(ccx.tcx.map.span(fn_id.node), + "reached the recursion limit during monomorphization"); } + ccx.monomorphizing.borrow_mut().insert(fn_id, depth + 1); + let s = ccx.tcx.map.with_path(fn_id.node, |path| { mangle_exported_name(ccx, path, mono_ty, fn_id.node) }); debug!("monomorphize_fn mangled to {}", s); - let mk_lldecl = || { + let mk_decl = || { let lldecl = decl_internal_rust_fn(ccx, false, f.sig.inputs.as_slice(), f.sig.output, s); - ccx.monomorphized.borrow_mut().insert(hash_id, lldecl); - lldecl + let decl = pod_value(ccx.tcx(), lldecl, mono_ty); + ccx.monomorphized.borrow_mut().insert(hash_id, decl); + decl }; - let lldecl = match map_node { + let decl = match map_node { ast_map::NodeItem(i) => { match *i { - ast::Item { - node: ast::ItemFn(decl, _, _, _, body), - .. - } => { - let d = mk_lldecl(); - set_llvm_fn_attrs(i.attrs.as_slice(), d); - trans_fn(ccx, decl, body, d, Some(psubsts), fn_id.node, []); - d - } - _ => { - ccx.sess().bug("Can't monomorphize this kind of item") - } + ast::Item { + node: ast::ItemFn(decl, _, _, _, body), + .. + } => { + let d = mk_decl(); + set_llvm_fn_attrs(i.attrs.as_slice(), d.val); + trans_fn(ccx, decl, body, d.val, Some(psubsts), fn_id.node, []); + d + } + _ => ccx.sess().bug("Can't monomorphize this kind of item") } } ast_map::NodeForeignItem(i) => { - let simple = intrinsic::get_simple_intrinsic(ccx, i); - match simple { - Some(decl) => decl, + match intrinsic::get_simple_intrinsic(ccx, i) { + Some(decl) => { + pod_value(ccx.tcx(), decl, mono_ty) + } None => { - let d = mk_lldecl(); - intrinsic::trans_intrinsic(ccx, d, i, psubsts, ref_id); + let d = mk_decl(); + intrinsic::trans_intrinsic(ccx, d.val, i, psubsts, ref_id); d } } @@ -221,8 +215,8 @@ pub fn monomorphic_fn(ccx: &CrateContext, let parent = ccx.tcx.map.get_parent(fn_id.node); let tvs = ty::enum_variants(ccx.tcx(), local_def(parent)); let this_tv = *tvs.iter().find(|tv| { tv.id.node == fn_id.node}).unwrap(); - let d = mk_lldecl(); - set_inline_hint(d); + let d = mk_decl(); + set_inline_hint(d.val); match v.node.kind { ast::TupleVariantKind(ref args) => { trans_enum_variant(ccx, @@ -231,7 +225,7 @@ pub fn monomorphic_fn(ccx: &CrateContext, args.as_slice(), this_tv.disr_val, Some(psubsts), - d); + d.val); } ast::StructVariantKind(_) => ccx.sess().bug("can't monomorphize struct variants"), @@ -239,17 +233,17 @@ pub fn monomorphic_fn(ccx: &CrateContext, d } ast_map::NodeMethod(mth) => { - let d = mk_lldecl(); - set_llvm_fn_attrs(mth.attrs.as_slice(), d); - trans_fn(ccx, mth.decl, mth.body, d, Some(psubsts), mth.id, []); + let d = mk_decl(); + set_llvm_fn_attrs(mth.attrs.as_slice(), d.val); + trans_fn(ccx, mth.decl, mth.body, d.val, Some(psubsts), mth.id, []); d } ast_map::NodeTraitMethod(method) => { match *method { ast::Provided(mth) => { - let d = mk_lldecl(); - set_llvm_fn_attrs(mth.attrs.as_slice(), d); - trans_fn(ccx, mth.decl, mth.body, d, Some(psubsts), mth.id, []); + let d = mk_decl(); + set_llvm_fn_attrs(mth.attrs.as_slice(), d.val); + trans_fn(ccx, mth.decl, mth.body, d.val, Some(psubsts), mth.id, []); d } _ => { @@ -259,14 +253,14 @@ pub fn monomorphic_fn(ccx: &CrateContext, } } ast_map::NodeStructCtor(struct_def) => { - let d = mk_lldecl(); - set_inline_hint(d); + let d = mk_decl(); + set_inline_hint(d.val); base::trans_tuple_struct(ccx, struct_def.fields.as_slice(), struct_def.ctor_id.expect("ast-mapped tuple struct \ didn't have a ctor id"), Some(psubsts), - d); + d.val); d } @@ -283,7 +277,7 @@ pub fn monomorphic_fn(ccx: &CrateContext, ccx.monomorphizing.borrow_mut().insert(fn_id, depth); debug!("leaving monomorphic fn {}", ty::item_path_str(ccx.tcx(), fn_id)); - (lldecl, must_cast) + decl } pub fn make_mono_id(ccx: &CrateContext, @@ -292,23 +286,17 @@ pub fn make_mono_id(ccx: &CrateContext, // FIXME (possibly #5801): Need a lot of type hints to get // .collect() to work. let substs_iter = substs.self_ty.iter().chain(substs.tys.iter()); - let precise_param_ids: Vec<(ty::t, Option<@Vec >)> = match substs.vtables { - Some(vts) => { - debug!("make_mono_id vtables={} substs={}", - vts.repr(ccx.tcx()), substs.tys.repr(ccx.tcx())); - let vts_iter = substs.self_vtables.iter().chain(vts.iter()); - vts_iter.zip(substs_iter).map(|(vtable, subst)| { - let v = vtable.map(|vt| meth::vtable_id(ccx, vt)); - (*subst, if !v.is_empty() { Some(@v) } else { None }) - }).collect() - } - None => substs_iter.map(|subst| (*subst, None::<@Vec >)).collect() + let param_ids: Vec = match substs.vtables { + Some(vts) => { + debug!("make_mono_id vtables={} substs={}", + vts.repr(ccx.tcx()), substs.tys.repr(ccx.tcx())); + let vts_iter = substs.self_vtables.iter().chain(vts.iter()); + vts_iter.zip(substs_iter).map(|(vtable, subst)| { + let v = vtable.map(|vt| meth::vtable_id(ccx, vt)); + MonoParamId(*subst, if !v.is_empty() { Some(@v) } else { None }) + }).collect() + } + None => substs_iter.map(|subst| MonoParamId(*subst, None)).collect() }; - - - let param_ids = precise_param_ids.iter().map(|x| { - let (a, b) = *x; - mono_precise(a, b) - }).collect(); @mono_id_ {def: item, params: param_ids} } diff --git a/src/librustc/middle/trans/reflect.rs b/src/librustc/middle/trans/reflect.rs index a0c1b0c042abc..ecf135214aa3e 100644 --- a/src/librustc/middle/trans/reflect.rs +++ b/src/librustc/middle/trans/reflect.rs @@ -9,17 +9,15 @@ // except according to those terms. use back::link::mangle_internal_name_by_path_and_seq; -use lib::llvm::{ValueRef, llvm}; +use lib::llvm::llvm; use middle::trans::adt; use middle::trans::base::*; use middle::trans::build::*; -use middle::trans::callee::ArgVals; use middle::trans::callee; use middle::trans::common::*; use middle::trans::datum::*; use middle::trans::glue; use middle::trans::machine; -use middle::trans::meth; use middle::trans::type_::Type; use middle::trans::type_of::*; use middle::ty; @@ -27,35 +25,31 @@ use util::ppaux::ty_to_str; use arena::TypedArena; use std::libc::c_uint; -use std::vec; use syntax::ast::DefId; use syntax::ast; use syntax::ast_map; use syntax::parse::token::{InternedString, special_idents}; use syntax::parse::token; -pub struct Reflector<'a> { - visitor_val: ValueRef, - visitor_methods: @Vec<@ty::Method> , +struct Reflector<'a> { + visitor_datum: Datum, + visitor_methods: @Vec<@ty::Method>, final_bcx: &'a Block<'a>, - tydesc_ty: Type, + tydesc_ptr: ty::t, + tydesc_ptr_llty: Type, bcx: &'a Block<'a> } impl<'a> Reflector<'a> { - pub fn c_uint(&mut self, u: uint) -> ValueRef { - C_uint(self.bcx.ccx(), u) + fn c_uint(&self, u: uint) -> Datum { + pod_value(self.bcx.tcx(), C_uint(self.bcx.ccx(), u), ty::mk_uint()) } - pub fn c_int(&mut self, i: int) -> ValueRef { - C_int(self.bcx.ccx(), i) + fn c_bool(&self, b: bool) -> Datum { + pod_value(self.bcx.tcx(), C_bool(self.bcx.ccx(), b), ty::mk_bool()) } - pub fn c_bool(&mut self, b: bool) -> ValueRef { - C_bool(self.bcx.ccx(), b) - } - - pub fn c_slice(&mut self, s: InternedString) -> ValueRef { + fn c_slice(&self, s: InternedString) -> Datum { // We're careful to not use first class aggregates here because that // will kick us off fast isel. (Issue #4352.) let bcx = self.bcx; @@ -66,31 +60,44 @@ impl<'a> Reflector<'a> { let c_str = PointerCast(bcx, C_cstr(bcx.ccx(), s), Type::i8p(bcx.ccx())); Store(bcx, c_str, GEPi(bcx, scratch.val, [ 0, 0 ])); Store(bcx, len, GEPi(bcx, scratch.val, [ 0, 1 ])); - scratch.val + scratch } - pub fn c_size_and_align(&mut self, t: ty::t) -> Vec { + fn c_size_and_align(&self, t: ty::t) -> [Datum, ..2] { let tr = type_of(self.bcx.ccx(), t); - let s = machine::llsize_of_real(self.bcx.ccx(), tr); - let a = machine::llalign_of_min(self.bcx.ccx(), tr); - return vec!(self.c_uint(s as uint), - self.c_uint(a as uint)); + [ + self.c_uint(machine::llsize_of_real(self.bcx.ccx(), tr) as uint), + self.c_uint(machine::llalign_of_min(self.bcx.ccx(), tr) as uint) + ] } - pub fn c_tydesc(&mut self, t: ty::t) -> ValueRef { + fn c_tydesc(&self, t: ty::t) -> Datum { let bcx = self.bcx; let static_ti = get_tydesc(bcx.ccx(), t); glue::lazily_emit_visit_glue(bcx.ccx(), static_ti); - PointerCast(bcx, static_ti.tydesc, self.tydesc_ty.ptr_to()) + let ptr = PointerCast(bcx, static_ti.tydesc, self.tydesc_ptr_llty); + pod_value(self.bcx.tcx(), ptr, self.tydesc_ptr) + } + + fn c_mt(&self, mt: &ty::mt) -> [Datum, ..2] { + [self.c_uint(mt.mutbl as uint), self.c_tydesc(mt.ty)] } - pub fn c_mt(&mut self, mt: &ty::mt) -> Vec { - vec!(self.c_uint(mt.mutbl as uint), - self.c_tydesc(mt.ty)) + fn vstore_name_and_extra(&self, + t: ty::t, + vstore: ty::vstore) + -> (&'static str, Option<[Datum, ..3]>) { + match vstore { + ty::vstore_fixed(n) => { + let size_align = self.c_size_and_align(t); + ("fixed", Some([self.c_uint(n), size_align[0], size_align[1]])) + } + ty::vstore_slice(_) => ("slice", None), + ty::vstore_uniq => ("uniq", None), + } } - pub fn visit(&mut self, ty_name: &str, args: &[ValueRef]) { - let fcx = self.bcx.fcx; + fn visit_inner>>(self, ty_name: &str, args: I) -> Reflector<'a> { let tcx = self.bcx.tcx(); let mth_idx = ty::method_idx(token::str_to_ident(~"visit_" + ty_name), self.visitor_methods.as_slice()).expect( @@ -98,56 +105,42 @@ impl<'a> Reflector<'a> { let mth_ty = ty::mk_bare_fn(tcx, self.visitor_methods.get(mth_idx).fty.clone()); - let v = self.visitor_val; - debug!("passing {} args:", args.len()); + let visitor = self.visitor_datum.to_expr_datum(); let mut bcx = self.bcx; - for (i, a) in args.iter().enumerate() { - debug!("arg {}: {}", i, bcx.val_to_str(*a)); - } - let result = unpack_result!(bcx, callee::trans_call_inner( - self.bcx, None, mth_ty, - |bcx, _| meth::trans_trait_callee_from_llval(bcx, - mth_ty, - mth_idx, - v), - ArgVals(args), None)); + let result = unpack_result!(bcx, callee::trans_call( + bcx, None, + callee::TraitMethod(mth_ty, mth_idx), + Some(visitor).move_iter().chain(args), + |bcx, arg_datum| DatumBlock(bcx, arg_datum), + None)); let result = bool_to_i1(bcx, result); - let next_bcx = fcx.new_temp_block("next"); + let next_bcx = self.bcx.fcx.new_temp_block("next"); CondBr(bcx, result, next_bcx.llbb, self.final_bcx.llbb); - self.bcx = next_bcx + + Reflector { + bcx: next_bcx, + ..self + } } - pub fn bracketed(&mut self, - bracket_name: &str, - extra: &[ValueRef], - inner: |&mut Reflector|) { - self.visit("enter_" + bracket_name, extra); - inner(self); - self.visit("leave_" + bracket_name, extra); + fn visit(self, ty_name: &str, args: &[Datum]) -> Reflector<'a> { + self.visit_inner(ty_name, args.iter().map(|arg| arg.to_expr_datum())) } - pub fn vstore_name_and_extra(&mut self, - t: ty::t, - vstore: ty::vstore) - -> (~str, Vec ) { - match vstore { - ty::vstore_fixed(n) => { - let extra = vec::append(vec!(self.c_uint(n)), - self.c_size_and_align(t) - .as_slice()); - (~"fixed", extra) - } - ty::vstore_slice(_) => (~"slice", Vec::new()), - ty::vstore_uniq => (~"uniq", Vec::new()), - } + fn bracketed>>(self, + bracket_name: &str, extra: || -> I, + inner: |Reflector<'a>| -> Reflector<'a>) + -> Reflector<'a> { + inner(self.visit_inner("enter_" + bracket_name, extra())) + .visit_inner("leave_" + bracket_name, extra()) } - pub fn leaf(&mut self, name: &str) { - self.visit(name, []); + fn leaf(self, name: &str) -> Reflector<'a> { + self.visit(name, []) } // Entrypoint - pub fn visit_ty(&mut self, t: ty::t) { + fn visit_ty(self, t: ty::t) -> Reflector<'a> { let bcx = self.bcx; let tcx = bcx.tcx(); debug!("reflect::visit_ty {}", ty_to_str(bcx.tcx(), t)); @@ -171,19 +164,26 @@ impl<'a> Reflector<'a> { ty::ty_float(ast::TyF64) => self.leaf("f64"), ty::ty_unboxed_vec(ref mt) => { - let values = self.c_mt(mt); - self.visit("vec", values.as_slice()) + self.visit("vec", self.c_mt(mt)) } // Should rename to str_*/vec_*. ty::ty_str(vst) => { let (name, extra) = self.vstore_name_and_extra(t, vst); - self.visit(~"estr_" + name, extra.as_slice()) + match extra { + Some(extra) => self.visit(~"estr_" + name, extra), + None => self.visit(~"estr_" + name, []) + } } ty::ty_vec(ref mt, vst) => { let (name, extra) = self.vstore_name_and_extra(t, vst); - let extra = vec::append(extra, self.c_mt(mt).as_slice()); - self.visit(~"evec_" + name, extra.as_slice()) + let mt = self.c_mt(mt); + match extra { + Some([n, size, align]) => { + self.visit(~"evec_" + name, [n, size, align, mt[0], mt[1]]) + } + None => self.visit(~"evec_" + name, [mt[0], mt[1]]) + } } // Should remove mt from box and uniq. ty::ty_box(typ) => { @@ -191,32 +191,36 @@ impl<'a> Reflector<'a> { ty: typ, mutbl: ast::MutImmutable, }); - self.visit("box", extra.as_slice()) + self.visit("box", extra) } ty::ty_uniq(typ) => { let extra = self.c_mt(&ty::mt { ty: typ, mutbl: ast::MutImmutable, }); - self.visit("uniq", extra.as_slice()) + self.visit("uniq", extra) } ty::ty_ptr(ref mt) => { - let extra = self.c_mt(mt); - self.visit("ptr", extra.as_slice()) + self.visit("ptr", self.c_mt(mt)) } ty::ty_rptr(_, ref mt) => { - let extra = self.c_mt(mt); - self.visit("rptr", extra.as_slice()) + self.visit("rptr", self.c_mt(mt)) } ty::ty_tup(ref tys) => { - let extra = vec::append(vec!(self.c_uint(tys.len())), - self.c_size_and_align(t).as_slice()); - self.bracketed("tup", extra.as_slice(), |this| { + let size_align = self.c_size_and_align(t); + let extra = [ + self.c_uint(tys.len()), + size_align[0], + size_align[1] + ]; + self.bracketed("tup", + || extra.iter().map(|arg| arg.to_expr_datum()), + |mut this| { for (i, t) in tys.iter().enumerate() { - let extra = vec!(this.c_uint(i), this.c_tydesc(*t)); - this.visit("tup_field", extra.as_slice()); + this = this.visit("tup_field", [this.c_uint(i), this.c_tydesc(*t)]); } + this }) } @@ -224,15 +228,19 @@ impl<'a> Reflector<'a> { // FIXME (#4809): visitor should break out bare fns from other fns ty::ty_closure(ref fty) => { let pureval = ast_purity_constant(fty.purity); - let sigilval = ast_sigil_constant(fty.sigil); + let sigilval = match fty.sigil { + ast::OwnedSigil => 2u, + ast::ManagedSigil => 3u, + ast::BorrowedSigil => 4u, + }; let retval = if ty::type_is_bot(fty.sig.output) {0u} else {1u}; - let extra = vec!(self.c_uint(pureval), - self.c_uint(sigilval), - self.c_uint(fty.sig.inputs.len()), - self.c_uint(retval)); - self.visit("enter_fn", extra.as_slice()); - self.visit_sig(retval, &fty.sig); - self.visit("leave_fn", extra.as_slice()); + let extra = [self.c_uint(pureval), + self.c_uint(sigilval), + self.c_uint(fty.sig.inputs.len()), + self.c_uint(retval)]; + self.visit("enter_fn", extra) + .visit_sig(retval, &fty.sig) + .visit("leave_fn", extra) } // FIXME (#2594): fetch constants out of intrinsic:: for the @@ -241,13 +249,13 @@ impl<'a> Reflector<'a> { let pureval = ast_purity_constant(fty.purity); let sigilval = 0u; let retval = if ty::type_is_bot(fty.sig.output) {0u} else {1u}; - let extra = vec!(self.c_uint(pureval), - self.c_uint(sigilval), - self.c_uint(fty.sig.inputs.len()), - self.c_uint(retval)); - self.visit("enter_fn", extra.as_slice()); - self.visit_sig(retval, &fty.sig); - self.visit("leave_fn", extra.as_slice()); + let extra = [self.c_uint(pureval), + self.c_uint(sigilval), + self.c_uint(fty.sig.inputs.len()), + self.c_uint(retval)]; + self.visit("enter_fn", extra) + .visit_sig(retval, &fty.sig) + .visit("leave_fn", extra) } ty::ty_struct(did, ref substs) => { @@ -258,21 +266,29 @@ impl<'a> Reflector<'a> { special_idents::unnamed_field.name; } - let extra = vec::append(vec!( - self.c_slice(token::intern_and_get_ident(ty_to_str(tcx, - t))), - self.c_bool(named_fields), - self.c_uint(fields.len()) - ), self.c_size_and_align(t).as_slice()); - self.bracketed("class", extra.as_slice(), |this| { + let size_align = self.c_size_and_align(t); + let name = self.c_slice(token::intern_and_get_ident(ty_to_str(tcx, t))); + let extra = [ + self.c_bool(named_fields), + self.c_uint(fields.len()), + size_align[0], size_align[1] + ]; + self.bracketed("class", + || { + let name = Datum(name.val, name.ty, RvalueExpr(Rvalue(name.kind.mode))); + Some(name).move_iter().chain(extra.iter().map(|arg| arg.to_expr_datum())) + }, |mut this| { for (i, field) in fields.iter().enumerate() { - let extra = vec::append(vec!( - this.c_uint(i), - this.c_slice(token::get_ident(field.ident)), - this.c_bool(named_fields) - ), this.c_mt(&field.mt).as_slice()); - this.visit("class_field", extra.as_slice()); + let mt = this.c_mt(&field.mt); + let name = this.c_slice(token::get_ident(field.ident)).to_expr_datum(); + let extra = [this.c_bool(named_fields), mt[0], mt[1]]; + this = this.visit_inner("class_field", + Some(this.c_uint(i).to_expr_datum()).move_iter() + .chain(Some(name).move_iter()) + .chain(extra.iter().map(|arg| arg.to_expr_datum())) + ); } + this }) } @@ -286,10 +302,9 @@ impl<'a> Reflector<'a> { let variants = ty::substd_enum_variants(ccx.tcx(), did, substs); let llptrty = type_of(ccx, t).ptr_to(); let opaquety = ty::get_opaque_ty(ccx.tcx()).unwrap(); - let opaqueptrty = ty::mk_ptr(ccx.tcx(), ty::mt { ty: opaquety, - mutbl: ast::MutImmutable }); + let opaqueptrty = ty::mk_imm_ptr(ccx.tcx(), opaquety); - let make_get_disr = || { + let get_disr = { let sym = mangle_internal_name_by_path_and_seq( ast_map::Values([].iter()).chain(None), "get_disr"); @@ -316,69 +331,74 @@ impl<'a> Reflector<'a> { None => {} }; finish_fn(&fcx, bcx); - llfdecl + pod_value(bcx.tcx(), llfdecl, ty::mk_imm_ptr(bcx.tcx(), ty::mk_nil())) }; - let enum_args = vec::append(vec!(self.c_uint(variants.len()), - make_get_disr()), - self.c_size_and_align(t) - .as_slice()); - self.bracketed("enum", enum_args.as_slice(), |this| { + let size_align = self.c_size_and_align(t); + let enum_args = [ + self.c_uint(variants.len()), + get_disr, + size_align[0], + size_align[1] + ]; + self.bracketed("enum", + || enum_args.iter().map(|arg| arg.to_expr_datum()), + |mut this| { for (i, v) in variants.iter().enumerate() { - let name = token::get_ident(v.name); - let variant_args = [this.c_uint(i), - C_u64(ccx, v.disr_val), - this.c_uint(v.args.len()), - this.c_slice(name)]; - this.bracketed("enum_variant", - variant_args, - |this| { + let args = [ + this.c_uint(i), + pod_value(this.bcx.tcx(), C_u64(ccx, v.disr_val), ty::mk_u64()), + this.c_uint(v.args.len()), + ]; + let name = this.c_slice(token::get_ident(v.name)); + this = this.bracketed("enum_variant", || { + let name = Datum(name.val, name.ty, RvalueExpr(Rvalue(name.kind.mode))); + args.iter().map(|arg| arg.to_expr_datum()).chain(Some(name).move_iter()) + }, |mut this| { for (j, a) in v.args.iter().enumerate() { - let bcx = this.bcx; - let null = C_null(llptrty); - let ptr = adt::trans_field_ptr(bcx, repr, null, v.disr_val, j); - let offset = p2i(ccx, ptr); - let field_args = [this.c_uint(j), - offset, - this.c_tydesc(*a)]; - this.visit("enum_variant_field", - field_args); + let offset = p2i(ccx, adt::trans_field_ptr(this.bcx, repr, + C_null(llptrty), + v.disr_val, j)); + this = this.visit("enum_variant_field", [ + this.c_uint(j), + pod_value(this.bcx.tcx(), offset, ty::mk_int()), + this.c_tydesc(*a) + ]); } + this }) } + this }) } - ty::ty_trait(..) => { - let extra = [ - self.c_slice(token::intern_and_get_ident(ty_to_str(tcx, t))) - ]; - self.visit("trait", extra); + ty::ty_trait(_) => { + let name = self.c_slice(token::intern_and_get_ident(ty_to_str(tcx, t))); + self.visit_inner("trait", Some(name.to_expr_datum()).move_iter()) } // Miscellaneous extra types ty::ty_infer(_) => self.leaf("infer"), ty::ty_err => self.leaf("err"), - ty::ty_param(ref p) => { - let extra = vec!(self.c_uint(p.idx)); - self.visit("param", extra.as_slice()) - } + ty::ty_param(ref p) => self.visit("param", [self.c_uint(p.idx)]), ty::ty_self(..) => self.leaf("self") } } - pub fn visit_sig(&mut self, retval: uint, sig: &ty::FnSig) { + fn visit_sig(mut self, retval: uint, sig: &ty::FnSig) -> Reflector<'a> { for (i, arg) in sig.inputs.iter().enumerate() { let modeval = 5u; // "by copy" - let extra = vec!(self.c_uint(i), - self.c_uint(modeval), - self.c_tydesc(*arg)); - self.visit("fn_input", extra.as_slice()); + self = self.visit("fn_input", [ + self.c_uint(i), + self.c_uint(modeval), + self.c_tydesc(*arg) + ]); } - let extra = vec!(self.c_uint(retval), - self.c_bool(sig.variadic), - self.c_tydesc(sig.output)); - self.visit("fn_output", extra.as_slice()); + self.visit("fn_output", [ + self.c_uint(retval), + self.c_bool(sig.variadic), + self.c_tydesc(sig.output) + ]) } } @@ -386,34 +406,24 @@ impl<'a> Reflector<'a> { pub fn emit_calls_to_trait_visit_ty<'a>( bcx: &'a Block<'a>, t: ty::t, - visitor_val: ValueRef, + visitor_datum: Datum, visitor_trait_id: DefId) -> &'a Block<'a> { - let fcx = bcx.fcx; - let final = fcx.new_temp_block("final"); - let tydesc_ty = ty::get_tydesc_ty(bcx.tcx()).unwrap(); - let tydesc_ty = type_of(bcx.ccx(), tydesc_ty); - let mut r = Reflector { - visitor_val: visitor_val, + let final = bcx.fcx.new_temp_block("final"); + let tydesc_ptr = ty::mk_imm_ptr(bcx.tcx(), ty::get_tydesc_ty(bcx.tcx()).unwrap()); + let r = Reflector { + visitor_datum: visitor_datum, visitor_methods: ty::trait_methods(bcx.tcx(), visitor_trait_id), final_bcx: final, - tydesc_ty: tydesc_ty, + tydesc_ptr: tydesc_ptr, + tydesc_ptr_llty: type_of(bcx.ccx(), tydesc_ptr), bcx: bcx }; - r.visit_ty(t); - Br(r.bcx, final.llbb); - return final; -} - -pub fn ast_sigil_constant(sigil: ast::Sigil) -> uint { - match sigil { - ast::OwnedSigil => 2u, - ast::ManagedSigil => 3u, - ast::BorrowedSigil => 4u, - } + Br(r.visit_ty(t).bcx, final.llbb); + final } -pub fn ast_purity_constant(purity: ast::Purity) -> uint { +fn ast_purity_constant(purity: ast::Purity) -> uint { match purity { ast::UnsafeFn => 1u, ast::ImpureFn => 2u, diff --git a/src/librustc/middle/trans/tvec.rs b/src/librustc/middle/trans/tvec.rs index 1a54c25e36408..9704564d73838 100644 --- a/src/librustc/middle/trans/tvec.rs +++ b/src/librustc/middle/trans/tvec.rs @@ -332,11 +332,10 @@ pub fn trans_uniq_vstore<'a>(bcx: &'a Block<'a>, Some(lit.span), "", StrDupUniqFnLangItem); - let bcx = callee::trans_lang_call( - bcx, - alloc_fn, - [ llptrval, llsizeval ], - Some(expr::SaveIn(lldestval.val))).bcx; + let bcx = callee::trans_lang_call(bcx, alloc_fn, [ + pod_value(bcx.tcx(), llptrval, ty::mk_imm_ptr(bcx.tcx(), ty::mk_u8())), + pod_value(bcx.tcx(), llsizeval, ty::mk_uint()) + ], Some(expr::SaveIn(lldestval.val))).bcx; return DatumBlock(bcx, lldestval).to_expr_datumblock(); } _ => {}