diff options
Diffstat (limited to 'src/librustc_trans/trans/expr.rs')
| -rw-r--r-- | src/librustc_trans/trans/expr.rs | 127 |
1 files changed, 47 insertions, 80 deletions
diff --git a/src/librustc_trans/trans/expr.rs b/src/librustc_trans/trans/expr.rs index b39029d3b94..b7ac0f49754 100644 --- a/src/librustc_trans/trans/expr.rs +++ b/src/librustc_trans/trans/expr.rs @@ -8,28 +8,26 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! - * # Translation of Expressions - * - * Public entry points: - * - * - `trans_into(bcx, expr, dest) -> bcx`: evaluates an expression, - * storing the result into `dest`. This is the preferred form, if you - * can manage it. - * - * - `trans(bcx, expr) -> DatumBlock`: evaluates an expression, yielding - * `Datum` with the result. You can then store the datum, inspect - * the value, etc. This may introduce temporaries if the datum is a - * structural type. - * - * - `trans_to_lvalue(bcx, expr, "...") -> DatumBlock`: evaluates an - * expression and ensures that the result has a cleanup associated with it, - * creating a temporary stack slot if necessary. - * - * - `trans_local_var -> Datum`: looks up a local variable or upvar. - * - * See doc.rs for more comments. - */ +//! # Translation of Expressions +//! +//! Public entry points: +//! +//! - `trans_into(bcx, expr, dest) -> bcx`: evaluates an expression, +//! storing the result into `dest`. This is the preferred form, if you +//! can manage it. +//! +//! - `trans(bcx, expr) -> DatumBlock`: evaluates an expression, yielding +//! `Datum` with the result. You can then store the datum, inspect +//! the value, etc. This may introduce temporaries if the datum is a +//! structural type. +//! +//! - `trans_to_lvalue(bcx, expr, "...") -> DatumBlock`: evaluates an +//! expression and ensures that the result has a cleanup associated with it, +//! creating a temporary stack slot if necessary. +//! +//! - `trans_local_var -> Datum`: looks up a local variable or upvar. +//! +//! See doc.rs for more comments. #![allow(non_camel_case_types)] @@ -82,15 +80,12 @@ impl Dest { } } +/// This function is equivalent to `trans(bcx, expr).store_to_dest(dest)` but it may generate +/// better optimized LLVM code. pub fn trans_into<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr, dest: Dest) -> Block<'blk, 'tcx> { - /*! - * This function is equivalent to `trans(bcx, expr).store_to_dest(dest)` - * but it may generate better optimized LLVM code. - */ - let mut bcx = bcx; if bcx.tcx().adjustments.borrow().contains_key(&expr.id) { @@ -124,16 +119,12 @@ pub fn trans_into<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, bcx.fcx.pop_and_trans_ast_cleanup_scope(bcx, expr.id) } +/// Translates an expression, returning a datum (and new block) encapsulating the result. When +/// possible, it is preferred to use `trans_into`, as that may avoid creating a temporary on the +/// stack. pub fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr) -> DatumBlock<'blk, 'tcx, Expr> { - /*! - * Translates an expression, returning a datum (and new block) - * encapsulating the result. When possible, it is preferred to - * use `trans_into`, as that may avoid creating a temporary on - * the stack. - */ - debug!("trans(expr={})", bcx.expr_to_string(expr)); let mut bcx = bcx; @@ -157,15 +148,12 @@ pub fn get_dataptr(bcx: Block, fat_ptr: ValueRef) -> ValueRef { GEPi(bcx, fat_ptr, &[0u, abi::FAT_PTR_ADDR]) } +/// Helper for trans that apply adjustments from `expr` to `datum`, which should be the unadjusted +/// translation of `expr`. fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr, datum: Datum<'tcx, Expr>) -> DatumBlock<'blk, 'tcx, Expr> { - /*! - * Helper for trans that apply adjustments from `expr` to `datum`, - * which should be the unadjusted translation of `expr`. - */ - let mut bcx = bcx; let mut datum = datum; let adjustment = match bcx.tcx().adjustments.borrow().get(&expr.id).cloned() { @@ -480,34 +468,27 @@ fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } } +/// Translates an expression in "lvalue" mode -- meaning that it returns a reference to the memory +/// that the expr represents. +/// +/// If this expression is an rvalue, this implies introducing a temporary. In other words, +/// something like `x().f` is translated into roughly the equivalent of +/// +/// { tmp = x(); tmp.f } pub fn trans_to_lvalue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr, name: &str) -> DatumBlock<'blk, 'tcx, Lvalue> { - /*! - * Translates an expression in "lvalue" mode -- meaning that it - * returns a reference to the memory that the expr represents. - * - * If this expression is an rvalue, this implies introducing a - * temporary. In other words, something like `x().f` is - * translated into roughly the equivalent of - * - * { tmp = x(); tmp.f } - */ - let mut bcx = bcx; let datum = unpack_datum!(bcx, trans(bcx, expr)); return datum.to_lvalue_datum(bcx, name, expr.id); } +/// A version of `trans` that ignores adjustments. You almost certainly do not want to call this +/// directly. fn trans_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr) -> DatumBlock<'blk, 'tcx, Expr> { - /*! - * A version of `trans` that ignores adjustments. You almost - * certainly do not want to call this directly. - */ - let mut bcx = bcx; debug!("trans_unadjusted(expr={})", bcx.expr_to_string(expr)); @@ -1218,14 +1199,10 @@ fn trans_def_fn_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, DatumBlock::new(bcx, Datum::new(llfn, fn_ty, RvalueExpr(Rvalue::new(ByValue)))) } +/// Translates a reference to a local variable or argument. This always results in an lvalue datum. pub fn trans_local_var<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, def: def::Def) -> Datum<'tcx, Lvalue> { - /*! - * Translates a reference to a local variable or argument. - * This always results in an lvalue datum. - */ - let _icx = push_ctxt("trans_local_var"); match def { @@ -1262,18 +1239,14 @@ pub fn trans_local_var<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } } +/// Helper for enumerating the field types of structs, enums, or records. The optional node ID here +/// is the node ID of the path identifying the enum variant in use. If none, this cannot possibly +/// an enum variant (so, if it is and `node_id_opt` is none, this function panics). pub fn with_field_tys<'tcx, R>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>, node_id_opt: Option<ast::NodeId>, op: |ty::Disr, (&[ty::field<'tcx>])| -> R) -> R { - /*! - * Helper for enumerating the field types of structs, enums, or records. - * The optional node ID here is the node ID of the path identifying the enum - * variant in use. If none, this cannot possibly an enum variant (so, if it - * is and `node_id_opt` is none, this function panics). - */ - match ty.sty { ty::ty_struct(did, ref substs) => { op(0, struct_fields(tcx, did, substs).as_slice()) @@ -2185,24 +2158,18 @@ fn deref_once<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, return r; + /// We microoptimize derefs of owned pointers a bit here. Basically, the idea is to make the + /// deref of an rvalue result in an rvalue. This helps to avoid intermediate stack slots in the + /// resulting LLVM. The idea here is that, if the `Box<T>` pointer is an rvalue, then we can + /// schedule a *shallow* free of the `Box<T>` pointer, and then return a ByRef rvalue into the + /// pointer. Because the free is shallow, it is legit to return an rvalue, because we know that + /// the contents are not yet scheduled to be freed. The language rules ensure that the contents + /// will be used (or moved) before the free occurs. fn deref_owned_pointer<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr, datum: Datum<'tcx, Expr>, content_ty: Ty<'tcx>) -> DatumBlock<'blk, 'tcx, Expr> { - /*! - * We microoptimize derefs of owned pointers a bit here. - * Basically, the idea is to make the deref of an rvalue - * result in an rvalue. This helps to avoid intermediate stack - * slots in the resulting LLVM. The idea here is that, if the - * `Box<T>` pointer is an rvalue, then we can schedule a *shallow* - * free of the `Box<T>` pointer, and then return a ByRef rvalue - * into the pointer. Because the free is shallow, it is legit - * to return an rvalue, because we know that the contents are - * not yet scheduled to be freed. The language rules ensure that the - * contents will be used (or moved) before the free occurs. - */ - match datum.kind { RvalueExpr(Rvalue { mode: ByRef }) => { let scope = cleanup::temporary_scope(bcx.tcx(), expr.id); |
