librustc: Emit enum variant constructor at callsite instead of via a call to a function.
This commit is contained in:
parent
9c9bdfd1c5
commit
cb404dd4fb
2 changed files with 77 additions and 5 deletions
|
@ -1704,6 +1704,61 @@ pub fn trans_enum_variant(ccx: &CrateContext,
|
||||||
llfndecl);
|
llfndecl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn trans_enum_variant_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);
|
||||||
|
adt::trans_start_init(bcx, &*repr, llresult, disr);
|
||||||
|
|
||||||
|
match args {
|
||||||
|
callee::ArgExprs(exprs) => {
|
||||||
|
for (i, expr) in exprs.iter().enumerate() {
|
||||||
|
let lldestptr = adt::trans_field_ptr(bcx, &*repr, llresult, disr, i);
|
||||||
|
bcx = expr::trans_into(bcx, *expr, expr::SaveIn(lldestptr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => 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,
|
pub fn trans_tuple_struct(ccx: &CrateContext,
|
||||||
_fields: &[ast::StructField],
|
_fields: &[ast::StructField],
|
||||||
ctor_id: ast::NodeId,
|
ctor_id: ast::NodeId,
|
||||||
|
|
|
@ -64,6 +64,10 @@ pub struct MethodData {
|
||||||
pub enum CalleeData {
|
pub enum CalleeData {
|
||||||
Closure(Datum<Lvalue>),
|
Closure(Datum<Lvalue>),
|
||||||
|
|
||||||
|
// Constructor for enum variant/tuple-like-struct
|
||||||
|
// i.e. Some, Ok
|
||||||
|
TupleVariantConstructor(subst::Substs, ty::Disr),
|
||||||
|
|
||||||
// Represents a (possibly monomorphized) top-level fn item or method
|
// 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
|
// item. Note that this is just the fn-ptr and is not a Rust closure
|
||||||
// value (which is a pair).
|
// value (which is a pair).
|
||||||
|
@ -158,11 +162,16 @@ fn trans<'a>(bcx: &'a Block<'a>, expr: &ast::Expr) -> Callee<'a> {
|
||||||
ref_expr.id))
|
ref_expr.id))
|
||||||
}
|
}
|
||||||
def::DefVariant(tid, vid, _) => {
|
def::DefVariant(tid, vid, _) => {
|
||||||
// nullary variants are not callable
|
let vinfo = ty::enum_variant_with_id(bcx.tcx(), tid, vid);
|
||||||
assert!(ty::enum_variant_with_id(bcx.tcx(),
|
let substs = node_id_substs(bcx, ExprId(ref_expr.id));
|
||||||
tid,
|
|
||||||
vid).args.len() > 0u);
|
// Nullary variants are not callable
|
||||||
fn_callee(bcx, trans_fn_ref(bcx, vid, ExprId(ref_expr.id)))
|
assert!(vinfo.args.len() > 0u);
|
||||||
|
|
||||||
|
Callee {
|
||||||
|
bcx: bcx,
|
||||||
|
data: TupleVariantConstructor(substs, vinfo.disr_val)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
def::DefStruct(def_id) => {
|
def::DefStruct(def_id) => {
|
||||||
fn_callee(bcx, trans_fn_ref(bcx, def_id, ExprId(ref_expr.id)))
|
fn_callee(bcx, trans_fn_ref(bcx, def_id, ExprId(ref_expr.id)))
|
||||||
|
@ -710,6 +719,14 @@ pub fn trans_call_inner<'a>(
|
||||||
arg_cleanup_scope, args,
|
arg_cleanup_scope, args,
|
||||||
dest.unwrap(), substs);
|
dest.unwrap(), substs);
|
||||||
}
|
}
|
||||||
|
TupleVariantConstructor(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_enum_variant_constructor(bcx, ctor_ty, disr,
|
||||||
|
args, dest.unwrap());
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Intrinsics should not become actual functions.
|
// Intrinsics should not become actual functions.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue