Skip to content

Trans enum & tuple struct constructors in place. #15765

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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