]> git.lizzy.rs Git - rust.git/commitdiff
librustc: Emit enum variant constructor at callsite instead of via a call to a function.
authorLuqman Aden <me@luqman.ca>
Thu, 10 Jul 2014 06:42:08 +0000 (23:42 -0700)
committerLuqman Aden <me@luqman.ca>
Fri, 18 Jul 2014 18:46:03 +0000 (11:46 -0700)
src/librustc/middle/trans/base.rs
src/librustc/middle/trans/callee.rs

index 98342bfbcdc320643aa0d804544d3d7e6c46887a..84db9e5335a1504509e40cc420c87b50d87b25ef 100644 (file)
@@ -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,
                           _fields: &[ast::StructField],
                           ctor_id: ast::NodeId,
 pub fn trans_tuple_struct(ccx: &CrateContext,
                           _fields: &[ast::StructField],
                           ctor_id: ast::NodeId,
index 8eab227ad16f7793da3e69836a979a58faf15fcf..608710a250825a8335106c09677e653775378988 100644 (file)
@@ -64,6 +64,10 @@ pub struct MethodData {
 pub enum CalleeData {
     Closure(Datum<Lvalue>),
 
 pub enum CalleeData {
     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
     // item. Note that this is just the fn-ptr and is not a Rust closure
     // value (which is a pair).
     // 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).
@@ -158,11 +162,16 @@ fn trans_def<'a>(bcx: &'a Block<'a>, def: def::Def, ref_expr: &ast::Expr)
                                                                 ref_expr.id))
             }
             def::DefVariant(tid, vid, _) => {
                                                                 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: TupleVariantConstructor(substs, vinfo.disr_val)
+                }
             }
             def::DefStruct(def_id) => {
                 fn_callee(bcx, trans_fn_ref(bcx, def_id, ExprId(ref_expr.id)))
             }
             def::DefStruct(def_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,
                                                    dest.unwrap(), substs);
         }
                                                    arg_cleanup_scope, args,
                                                    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.