Skip to content

Commit

Permalink
auto merge of #15765 : luqmana/rust/iec, r=pcwalton
Browse files Browse the repository at this point in the history
Fixes #15400.
  • Loading branch information
bors committed Jul 19, 2014
2 parents f05a2c9 + 61ded48 commit e0a6e2b
Show file tree
Hide file tree
Showing 7 changed files with 144 additions and 89 deletions.
12 changes: 3 additions & 9 deletions src/librustc/metadata/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -314,8 +314,7 @@ fn encode_enum_variant_info(ecx: &EncodeContext,
ebml_w: &mut Encoder,
id: NodeId,
variants: &[P<Variant>],
index: &mut Vec<entry<i64>>,
generics: &ast::Generics) {
index: &mut Vec<entry<i64>>) {
debug!("encode_enum_variant_info(id={:?})", id);

let mut disr_val = 0;
Expand Down Expand Up @@ -343,10 +342,6 @@ fn encode_enum_variant_info(ecx: &EncodeContext,
encode_stability(ebml_w, stab);

match variant.node.kind {
ast::TupleVariantKind(ref args)
if args.len() > 0 && generics.ty_params.len() == 0 => {
encode_symbol(ecx, ebml_w, variant.node.id);
}
ast::TupleVariantKind(_) => {},
ast::StructVariantKind(_) => {
let fields = ty::lookup_struct_fields(ecx.tcx, def_id);
Expand Down Expand Up @@ -1019,7 +1014,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
encode_stability(ebml_w, stab);
ebml_w.end_tag();
}
ItemEnum(ref enum_definition, ref generics) => {
ItemEnum(ref enum_definition, _) => {
add_to_index(item, ebml_w, index);

ebml_w.start_tag(tag_items_data_item);
Expand All @@ -1046,8 +1041,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
ebml_w,
item.id,
(*enum_definition).variants.as_slice(),
index,
generics);
index);
}
ItemStruct(struct_def, _) => {
let fields = ty::lookup_struct_fields(tcx, def_id);
Expand Down
7 changes: 3 additions & 4 deletions src/librustc/middle/trans/adt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -674,11 +674,10 @@ pub fn trans_case<'a>(bcx: &'a Block<'a>, r: &Repr, discr: Disr)
}

/**
* Begin initializing a new value of the given case of the given
* representation. The fields, if any, should then be initialized via
* `trans_field_ptr`.
* Set the discriminant for a new value of the given case of the given
* representation.
*/
pub fn trans_start_init(bcx: &Block, r: &Repr, val: ValueRef, discr: Disr) {
pub fn trans_set_discr(bcx: &Block, r: &Repr, val: ValueRef, discr: Disr) {
match *r {
CEnum(ity, min, max) => {
assert_discr_in_range(ity, min, max, discr);
Expand Down
108 changes: 56 additions & 52 deletions src/librustc/middle/trans/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@ use std::c_str::ToCStr;
use std::cell::{Cell, RefCell};
use std::rc::Rc;
use std::{i8, i16, i32, i64};
use std::gc::Gc;
use syntax::abi::{X86, X86_64, Arm, Mips, Mipsel, Rust, RustCall};
use syntax::abi::{RustIntrinsic, Abi};
use syntax::ast_util::{local_def, is_local};
Expand Down Expand Up @@ -1704,6 +1703,59 @@ pub fn trans_enum_variant(ccx: &CrateContext,
llfndecl);
}

pub fn trans_named_tuple_constructor<'a>(mut bcx: &'a Block<'a>,
ctor_ty: ty::t,
disr: ty::Disr,
args: callee::CallArgs,
dest: expr::Dest) -> Result<'a> {

let ccx = bcx.fcx.ccx;
let tcx = &ccx.tcx;

let result_ty = match ty::get(ctor_ty).sty {
ty::ty_bare_fn(ref bft) => bft.sig.output,
_ => ccx.sess().bug(
format!("trans_enum_variant_constructor: \
unexpected ctor return type {}",
ctor_ty.repr(tcx)).as_slice())
};

// Get location to store the result. If the user does not care about
// the result, just make a stack slot
let llresult = match dest {
expr::SaveIn(d) => d,
expr::Ignore => {
if !type_is_zero_size(ccx, result_ty) {
alloc_ty(bcx, result_ty, "constructor_result")
} else {
C_undef(type_of::type_of(ccx, result_ty))
}
}
};

if !type_is_zero_size(ccx, result_ty) {
let repr = adt::represent_type(ccx, result_ty);

match args {
callee::ArgExprs(exprs) => {
let fields = exprs.iter().map(|x| *x).enumerate().collect::<Vec<_>>();
bcx = expr::trans_adt(bcx, &*repr, disr, fields.as_slice(),
None, expr::SaveIn(llresult));
}
_ => ccx.sess().bug("expected expr as arguments for variant/struct tuple constructor")
}
}

// If the caller doesn't care about the result
// drop the temporary we made
let bcx = match dest {
expr::SaveIn(_) => bcx,
expr::Ignore => glue::drop_ty(bcx, llresult, result_ty)
};

Result::new(bcx, llresult)
}

pub fn trans_tuple_struct(ccx: &CrateContext,
_fields: &[ast::StructField],
ctor_id: ast::NodeId,
Expand Down Expand Up @@ -1746,7 +1798,6 @@ fn trans_enum_variant_or_tuple_like_struct(ccx: &CrateContext,

if !type_is_zero_size(fcx.ccx, result_ty) {
let repr = adt::represent_type(ccx, result_ty);
adt::trans_start_init(bcx, &*repr, fcx.llretptr.get().unwrap(), disr);
for (i, arg_datum) in arg_datums.move_iter().enumerate() {
let lldestptr = adt::trans_field_ptr(bcx,
&*repr,
Expand All @@ -1755,36 +1806,12 @@ fn trans_enum_variant_or_tuple_like_struct(ccx: &CrateContext,
i);
arg_datum.store_to(bcx, lldestptr);
}
adt::trans_set_discr(bcx, &*repr, fcx.llretptr.get().unwrap(), disr);
}

finish_fn(&fcx, bcx, result_ty);
}

fn trans_enum_def(ccx: &CrateContext, enum_definition: &ast::EnumDef,
sp: Span, id: ast::NodeId, vi: &[Rc<ty::VariantInfo>],
i: &mut uint) {
for variant in enum_definition.variants.iter() {
let disr_val = vi[*i].disr_val;
*i += 1;

match variant.node.kind {
ast::TupleVariantKind(ref args) if args.len() > 0 => {
let llfn = get_item_val(ccx, variant.node.id);
trans_enum_variant(ccx, id, &**variant, args.as_slice(),
disr_val, &param_substs::empty(), llfn);
}
ast::TupleVariantKind(_) => {
// Nothing to do.
}
ast::StructVariantKind(struct_def) => {
trans_struct_def(ccx, struct_def);
}
}
}

enum_variant_size_lint(ccx, enum_definition, sp, id);
}

fn enum_variant_size_lint(ccx: &CrateContext, enum_def: &ast::EnumDef, sp: Span, id: ast::NodeId) {
let mut sizes = Vec::new(); // does no allocation if no pushes, thankfully

Expand Down Expand Up @@ -1877,12 +1904,8 @@ pub fn trans_item(ccx: &CrateContext, item: &ast::Item) {
ast::ItemMod(ref m) => {
trans_mod(ccx, m);
}
ast::ItemEnum(ref enum_definition, ref generics) => {
if !generics.is_type_parameterized() {
let vi = ty::enum_variants(ccx.tcx(), local_def(item.id));
let mut i = 0;
trans_enum_def(ccx, enum_definition, item.span, item.id, vi.as_slice(), &mut i);
}
ast::ItemEnum(ref enum_definition, _) => {
enum_variant_size_lint(ccx, enum_definition, item.span, item.id);
}
ast::ItemStatic(_, m, ref expr) => {
// Recurse on the expression to catch items in blocks
Expand All @@ -1909,11 +1932,6 @@ pub fn trans_item(ccx: &CrateContext, item: &ast::Item) {
ast::ItemForeignMod(ref foreign_mod) => {
foreign::trans_foreign_mod(ccx, foreign_mod);
}
ast::ItemStruct(struct_def, ref generics) => {
if !generics.is_type_parameterized() {
trans_struct_def(ccx, struct_def);
}
}
ast::ItemTrait(..) => {
// Inside of this trait definition, we won't be actually translating any
// functions, but the trait still needs to be walked. Otherwise default
Expand All @@ -1926,20 +1944,6 @@ pub fn trans_item(ccx: &CrateContext, item: &ast::Item) {
}
}

pub fn trans_struct_def(ccx: &CrateContext, struct_def: Gc<ast::StructDef>) {
// If this is a tuple-like struct, translate the constructor.
match struct_def.ctor_id {
// 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);
trans_tuple_struct(ccx, struct_def.fields.as_slice(),
ctor_id, &param_substs::empty(), llfndecl);
}
Some(_) | None => {}
}
}

// Translate a module. Doing this amounts to translating the items in the
// module; there ends up being no artifact (aside from linkage names) of
// separate modules in the compiled program. That's because modules exist
Expand Down
77 changes: 68 additions & 9 deletions src/librustc/middle/trans/callee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
use arena::TypedArena;
use back::abi;
use back::link;
use driver::session;
use llvm::{ValueRef, get_param};
use llvm;
use metadata::csearch;
Expand Down Expand Up @@ -54,6 +55,7 @@ use util::ppaux::Repr;

use std::gc::Gc;
use syntax::ast;
use syntax::ast_map;
use synabi = syntax::abi;

pub struct MethodData {
Expand All @@ -64,6 +66,10 @@ pub struct MethodData {
pub enum CalleeData {
Closure(Datum<Lvalue>),

// Constructor for enum variant/tuple-like-struct
// i.e. Some, Ok
NamedTupleConstructor(subst::Substs, ty::Disr),

// 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).
Expand Down Expand Up @@ -134,6 +140,23 @@ fn trans<'a>(bcx: &'a Block<'a>, expr: &ast::Expr) -> Callee<'a> {
debug!("trans_def(def={}, ref_expr={})", def.repr(bcx.tcx()), ref_expr.repr(bcx.tcx()));
let expr_ty = node_id_type(bcx, ref_expr.id);
match def {
def::DefFn(did, _) if {
let def_id = if did.krate != ast::LOCAL_CRATE {
inline::maybe_instantiate_inline(bcx.ccx(), did)
} else {
did
};
match bcx.tcx().map.find(def_id.node) {
Some(ast_map::NodeStructCtor(_)) => true,
_ => false
}
} => {
let substs = node_id_substs(bcx, ExprId(ref_expr.id));
Callee {
bcx: bcx,
data: NamedTupleConstructor(substs, 0)
}
}
def::DefFn(did, _) if match ty::get(expr_ty).sty {
ty::ty_bare_fn(ref f) => f.abi == synabi::RustIntrinsic,
_ => false
Expand All @@ -158,14 +181,23 @@ fn trans<'a>(bcx: &'a Block<'a>, expr: &ast::Expr) -> Callee<'a> {
ref_expr.id))
}
def::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)))
let vinfo = ty::enum_variant_with_id(bcx.tcx(), tid, vid);
let substs = node_id_substs(bcx, ExprId(ref_expr.id));

// Nullary variants are not callable
assert!(vinfo.args.len() > 0u);

Callee {
bcx: bcx,
data: NamedTupleConstructor(substs, vinfo.disr_val)
}
}
def::DefStruct(def_id) => {
fn_callee(bcx, trans_fn_ref(bcx, def_id, ExprId(ref_expr.id)))
def::DefStruct(_) => {
let substs = node_id_substs(bcx, ExprId(ref_expr.id));
Callee {
bcx: bcx,
data: NamedTupleConstructor(substs, 0)
}
}
def::DefStatic(..) |
def::DefArg(..) |
Expand Down Expand Up @@ -490,8 +522,27 @@ pub fn trans_fn_ref_with_vtables(
}
};

// We must monomorphise if the fn has type parameters or is a default method.
let must_monomorphise = !substs.types.is_empty() || is_default;
// We must monomorphise if the fn has type parameters, is a default method,
// or is a named tuple constructor.
let must_monomorphise = if !substs.types.is_empty() || is_default {
true
} else if def_id.krate == ast::LOCAL_CRATE {
let map_node = session::expect(
ccx.sess(),
tcx.map.find(def_id.node),
|| "local item should be in ast map".to_string());

match map_node {
ast_map::NodeVariant(v) => match v.node.kind {
ast::TupleVariantKind(ref args) => args.len() > 0,
_ => false
},
ast_map::NodeStructCtor(_) => true,
_ => false
}
} else {
false
};

// Create a monomorphic version of generic functions
if must_monomorphise {
Expand Down Expand Up @@ -710,6 +761,14 @@ pub fn trans_call_inner<'a>(
arg_cleanup_scope, args,
dest.unwrap(), substs);
}
NamedTupleConstructor(substs, disr) => {
assert!(dest.is_some());
fcx.pop_custom_cleanup_scope(arg_cleanup_scope);

let ctor_ty = callee_ty.subst(bcx.tcx(), &substs);
return base::trans_named_tuple_constructor(bcx, ctor_ty, disr,
args, dest.unwrap());
}
};

// Intrinsics should not become actual functions.
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/trans/closure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -502,7 +502,6 @@ pub fn trans_unboxed_closure<'a>(
let repr = adt::represent_type(bcx.ccx(), node_id_type(bcx, id));

// Create the closure.
adt::trans_start_init(bcx, &*repr, dest_addr, 0);
for freevar in freevars_ptr.iter() {
let datum = expr::trans_local_var(bcx, freevar.def);
let upvar_slot_dest = adt::trans_field_ptr(bcx,
Expand All @@ -512,6 +511,7 @@ pub fn trans_unboxed_closure<'a>(
0);
bcx = datum.store_to(bcx, upvar_slot_dest);
}
adt::trans_set_discr(bcx, &*repr, dest_addr, 0);

bcx
}
Expand Down
Loading

0 comments on commit e0a6e2b

Please sign in to comment.