1 // Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 /*!
12 * See the section on datums in `doc.rs` for an overview of what
13 * Datums are and how they are intended to be used.
14 */
15
16 use lib;
17 use lib::llvm::ValueRef;
18 use middle::trans::base::*;
19 use middle::trans::build::*;
20 use middle::trans::common::*;
21 use middle::trans::cleanup;
22 use middle::trans::cleanup::CleanupMethods;
23 use middle::trans::expr;
24 use middle::trans::glue;
25 use middle::trans::tvec;
26 use middle::trans::type_of;
27 use middle::ty;
28 use util::ppaux::{ty_to_str};
29
30 use syntax::ast;
31
32 /**
33 * A `Datum` encapsulates the result of evaluating an expression. It
34 * describes where the value is stored, what Rust type the value has,
35 * whether it is addressed by reference, and so forth. Please refer
36 * the section on datums in `doc.rs` for more details.
37 */
38 #[deriving(Clone)]
39 pub struct Datum<K> {
40 /// The llvm value. This is either a pointer to the Rust value or
41 /// the value itself, depending on `kind` below.
42 pub val: ValueRef,
43
44 /// The rust type of the value.
45 pub ty: ty::t,
46
47 /// Indicates whether this is by-ref or by-value.
48 pub kind: K,
49 }
50
51 pub struct DatumBlock<'a, K> {
52 pub bcx: &'a Block<'a>,
53 pub datum: Datum<K>,
54 }
55
56 pub enum Expr {
57 /// a fresh value that was produced and which has no cleanup yet
58 /// because it has not yet "landed" into its permanent home
59 RvalueExpr(Rvalue),
60
61 /// `val` is a pointer into memory for which a cleanup is scheduled
62 /// (and thus has type *T). If you move out of an Lvalue, you must
63 /// zero out the memory (FIXME #5016).
64 LvalueExpr,
65 }
66
67 #[deriving(Clone)]
68 pub struct Lvalue;
69
70 pub struct Rvalue {
71 pub mode: RvalueMode
72 }
73
74 pub fn Rvalue(m: RvalueMode) -> Rvalue {
75 Rvalue { mode: m }
76 }
77
78 // Make Datum linear for more type safety.
79 impl Drop for Rvalue {
80 fn drop(&mut self) { }
81 }
82
83 #[deriving(Eq, TotalEq, Hash)]
84 pub enum RvalueMode {
85 /// `val` is a pointer to the actual value (and thus has type *T)
86 ByRef,
87
88 /// `val` is the actual value (*only used for immediates* like ints, ptrs)
89 ByValue,
90 }
91
92 pub fn Datum<K:KindOps>(val: ValueRef, ty: ty::t, kind: K) -> Datum<K> {
93 Datum { val: val, ty: ty, kind: kind }
94 }
95
96 pub fn DatumBlock<'a, K>(bcx: &'a Block<'a>,
97 datum: Datum<K>)
98 -> DatumBlock<'a, K> {
99 DatumBlock { bcx: bcx, datum: datum }
100 }
101
102 pub fn immediate_rvalue(val: ValueRef, ty: ty::t) -> Datum<Rvalue> {
103 return Datum(val, ty, Rvalue(ByValue));
104 }
105
106 pub fn immediate_rvalue_bcx<'a>(bcx: &'a Block<'a>,
107 val: ValueRef,
108 ty: ty::t)
109 -> DatumBlock<'a, Rvalue> {
110 return DatumBlock(bcx, immediate_rvalue(val, ty))
111 }
112
113
114 pub fn lvalue_scratch_datum<'a, A>(bcx: &'a Block<'a>,
115 ty: ty::t,
116 name: &str,
117 zero: bool,
118 scope: cleanup::ScopeId,
119 arg: A,
120 populate: |A, &'a Block<'a>, ValueRef|
121 -> &'a Block<'a>)
122 -> DatumBlock<'a, Lvalue> {
123 /*!
124 * Allocates temporary space on the stack using alloca() and
125 * returns a by-ref Datum pointing to it. The memory will be
126 * dropped upon exit from `scope`. The callback `populate` should
127 * initialize the memory. If `zero` is true, the space will be
128 * zeroed when it is allocated; this is not necessary unless `bcx`
129 * does not dominate the end of `scope`.
130 */
131
132 let llty = type_of::type_of(bcx.ccx(), ty);
133 let scratch = alloca_maybe_zeroed(bcx, llty, name, zero);
134
135 // Subtle. Populate the scratch memory *before* scheduling cleanup.
136 let bcx = populate(arg, bcx, scratch);
137 bcx.fcx.schedule_drop_mem(scope, scratch, ty);
138
139 DatumBlock(bcx, Datum(scratch, ty, Lvalue))
140 }
141
142 pub fn rvalue_scratch_datum(bcx: &Block,
143 ty: ty::t,
144 name: &str)
145 -> Datum<Rvalue> {
146 /*!
147 * Allocates temporary space on the stack using alloca() and
148 * returns a by-ref Datum pointing to it. If `zero` is true, the
149 * space will be zeroed when it is allocated; this is normally not
150 * necessary, but in the case of automatic rooting in match
151 * statements it is possible to have temporaries that may not get
152 * initialized if a certain arm is not taken, so we must zero
153 * them. You must arrange any cleanups etc yourself!
154 */
155
156 let llty = type_of::type_of(bcx.ccx(), ty);
157 let scratch = alloca_maybe_zeroed(bcx, llty, name, false);
158 Datum(scratch, ty, Rvalue(ByRef))
159 }
160
161 pub fn appropriate_rvalue_mode(ccx: &CrateContext, ty: ty::t) -> RvalueMode {
162 /*!
163 * Indicates the "appropriate" mode for this value,
164 * which is either by ref or by value, depending
165 * on whether type is immediate or not.
166 */
167
168 if type_is_zero_size(ccx, ty) {
169 ByValue
170 } else if type_is_immediate(ccx, ty) {
171 ByValue
172 } else {
173 ByRef
174 }
175 }
176
177 fn add_rvalue_clean(mode: RvalueMode,
178 fcx: &FunctionContext,
179 scope: cleanup::ScopeId,
180 val: ValueRef,
181 ty: ty::t) {
182 match mode {
183 ByValue => { fcx.schedule_drop_immediate(scope, val, ty); }
184 ByRef => { fcx.schedule_drop_mem(scope, val, ty); }
185 }
186 }
187
188 pub trait KindOps {
189
190 /**
191 * Take appropriate action after the value in `datum` has been
192 * stored to a new location.
193 */
194 fn post_store<'a>(&self,
195 bcx: &'a Block<'a>,
196 val: ValueRef,
197 ty: ty::t)
198 -> &'a Block<'a>;
199
200 /**
201 * True if this mode is a reference mode, meaning that the datum's
202 * val field is a pointer to the actual value
203 */
204 fn is_by_ref(&self) -> bool;
205
206 /**
207 * Converts to an Expr kind
208 */
209 fn to_expr_kind(self) -> Expr;
210
211 }
212
213 impl KindOps for Rvalue {
214 fn post_store<'a>(&self,
215 bcx: &'a Block<'a>,
216 _val: ValueRef,
217 _ty: ty::t)
218 -> &'a Block<'a> {
219 // No cleanup is scheduled for an rvalue, so we don't have
220 // to do anything after a move to cancel or duplicate it.
221 bcx
222 }
223
224 fn is_by_ref(&self) -> bool {
225 self.mode == ByRef
226 }
227
228 fn to_expr_kind(self) -> Expr {
229 RvalueExpr(self)
230 }
231 }
232
233 impl KindOps for Lvalue {
234 fn post_store<'a>(&self,
235 bcx: &'a Block<'a>,
236 val: ValueRef,
237 ty: ty::t)
238 -> &'a Block<'a> {
239 /*!
240 * If an lvalue is moved, we must zero out the memory in which
241 * it resides so as to cancel cleanup. If an @T lvalue is
242 * copied, we must increment the reference count.
243 */
244
245 if ty::type_needs_drop(bcx.tcx(), ty) {
246 if ty::type_moves_by_default(bcx.tcx(), ty) {
247 // cancel cleanup of affine values by zeroing out
248 let () = zero_mem(bcx, val, ty);
249 bcx
250 } else {
251 // incr. refcount for @T or newtype'd @T
252 glue::take_ty(bcx, val, ty)
253 }
254 } else {
255 bcx
256 }
257 }
258
259 fn is_by_ref(&self) -> bool {
260 true
261 }
262
263 fn to_expr_kind(self) -> Expr {
264 LvalueExpr
265 }
266 }
267
268 impl KindOps for Expr {
269 fn post_store<'a>(&self,
270 bcx: &'a Block<'a>,
271 val: ValueRef,
272 ty: ty::t)
273 -> &'a Block<'a> {
274 match *self {
275 LvalueExpr => Lvalue.post_store(bcx, val, ty),
276 RvalueExpr(ref r) => r.post_store(bcx, val, ty),
277 }
278 }
279
280 fn is_by_ref(&self) -> bool {
281 match *self {
282 LvalueExpr => Lvalue.is_by_ref(),
283 RvalueExpr(ref r) => r.is_by_ref()
284 }
285 }
286
287 fn to_expr_kind(self) -> Expr {
288 self
289 }
290 }
291
292 impl Datum<Rvalue> {
293 pub fn add_clean(self,
294 fcx: &FunctionContext,
295 scope: cleanup::ScopeId)
296 -> ValueRef {
297 /*!
298 * Schedules a cleanup for this datum in the given scope.
299 * That means that this datum is no longer an rvalue datum;
300 * hence, this function consumes the datum and returns the
301 * contained ValueRef.
302 */
303
304 add_rvalue_clean(self.kind.mode, fcx, scope, self.val, self.ty);
305 self.val
306 }
307
308 pub fn to_lvalue_datum_in_scope<'a>(self,
309 bcx: &'a Block<'a>,
310 name: &str,
311 scope: cleanup::ScopeId)
312 -> DatumBlock<'a, Lvalue> {
313 /*!
314 * Returns an lvalue datum (that is, a by ref datum with
315 * cleanup scheduled). If `self` is not already an lvalue,
316 * cleanup will be scheduled in the temporary scope for `expr_id`.
317 */
318 let fcx = bcx.fcx;
319
320 match self.kind.mode {
321 ByRef => {
322 add_rvalue_clean(ByRef, fcx, scope, self.val, self.ty);
323 DatumBlock(bcx, Datum(self.val, self.ty, Lvalue))
324 }
325
326 ByValue => {
327 lvalue_scratch_datum(
328 bcx, self.ty, name, false, scope, self,
329 |this, bcx, llval| this.store_to(bcx, llval))
330 }
331 }
332 }
333
334 pub fn to_ref_datum<'a>(self, bcx: &'a Block<'a>) -> DatumBlock<'a, Rvalue> {
335 let mut bcx = bcx;
336 match self.kind.mode {
337 ByRef => DatumBlock(bcx, self),
338 ByValue => {
339 let scratch = rvalue_scratch_datum(bcx, self.ty, "to_ref");
340 bcx = self.store_to(bcx, scratch.val);
341 DatumBlock(bcx, scratch)
342 }
343 }
344 }
345
346 pub fn to_appropriate_datum<'a>(self,
347 bcx: &'a Block<'a>)
348 -> DatumBlock<'a, Rvalue> {
349 match self.appropriate_rvalue_mode(bcx.ccx()) {
350 ByRef => {
351 self.to_ref_datum(bcx)
352 }
353 ByValue => {
354 match self.kind.mode {
355 ByValue => DatumBlock(bcx, self),
356 ByRef => {
357 let llval = load(bcx, self.val, self.ty);
358 DatumBlock(bcx, Datum(llval, self.ty, Rvalue(ByValue)))
359 }
360 }
361 }
362 }
363 }
364 }
365
366 /**
367 * Methods suitable for "expr" datums that could be either lvalues or
368 * rvalues. These include coercions into lvalues/rvalues but also a number
369 * of more general operations. (Some of those operations could be moved to
370 * the more general `impl<K> Datum<K>`, but it's convenient to have them
371 * here since we can `match self.kind` rather than having to implement
372 * generic methods in `KindOps`.)
373 */
374 impl Datum<Expr> {
375 fn match_kind<R>(self,
376 if_lvalue: |Datum<Lvalue>| -> R,
377 if_rvalue: |Datum<Rvalue>| -> R)
378 -> R {
379 let Datum { val, ty, kind } = self;
380 match kind {
381 LvalueExpr => if_lvalue(Datum(val, ty, Lvalue)),
382 RvalueExpr(r) => if_rvalue(Datum(val, ty, r)),
383 }
384 }
385
386 #[allow(dead_code)] // potentially useful
387 pub fn assert_lvalue(self, bcx: &Block) -> Datum<Lvalue> {
388 /*!
389 * Asserts that this datum *is* an lvalue and returns it.
390 */
391
392 self.match_kind(
393 |d| d,
394 |_| bcx.sess().bug("assert_lvalue given rvalue"))
395 }
396
397 pub fn assert_rvalue(self, bcx: &Block) -> Datum<Rvalue> {
398 /*!
399 * Asserts that this datum *is* an lvalue and returns it.
400 */
401
402 self.match_kind(
403 |_| bcx.sess().bug("assert_rvalue given lvalue"),
404 |r| r)
405 }
406
407 pub fn store_to_dest<'a>(self,
408 bcx: &'a Block<'a>,
409 dest: expr::Dest,
410 expr_id: ast::NodeId)
411 -> &'a Block<'a> {
412 match dest {
413 expr::Ignore => {
414 self.add_clean_if_rvalue(bcx, expr_id);
415 bcx
416 }
417 expr::SaveIn(addr) => {
418 self.store_to(bcx, addr)
419 }
420 }
421 }
422
423 pub fn add_clean_if_rvalue<'a>(self,
424 bcx: &'a Block<'a>,
425 expr_id: ast::NodeId) {
426 /*!
427 * Arranges cleanup for `self` if it is an rvalue. Use when
428 * you are done working with a value that may need drop.
429 */
430
431 self.match_kind(
432 |_| { /* Nothing to do, cleanup already arranged */ },
433 |r| {
434 let scope = cleanup::temporary_scope(bcx.tcx(), expr_id);
435 r.add_clean(bcx.fcx, scope);
436 })
437 }
438
439 pub fn clean<'a>(self,
440 bcx: &'a Block<'a>,
441 name: &'static str,
442 expr_id: ast::NodeId)
443 -> &'a Block<'a> {
444 /*!
445 * Ensures that `self` will get cleaned up, if it is not an lvalue
446 * already.
447 */
448
449 self.to_lvalue_datum(bcx, name, expr_id).bcx
450 }
451
452 pub fn to_lvalue_datum<'a>(self,
453 bcx: &'a Block<'a>,
454 name: &str,
455 expr_id: ast::NodeId)
456 -> DatumBlock<'a, Lvalue> {
457 self.match_kind(
458 |l| DatumBlock(bcx, l),
459 |r| {
460 let scope = cleanup::temporary_scope(bcx.tcx(), expr_id);
461 r.to_lvalue_datum_in_scope(bcx, name, scope)
462 })
463 }
464
465 pub fn to_rvalue_datum<'a>(self,
466 bcx: &'a Block<'a>,
467 name: &'static str)
468 -> DatumBlock<'a, Rvalue> {
469 /*!
470 * Ensures that we have an rvalue datum (that is, a datum with
471 * no cleanup scheduled).
472 */
473
474 self.match_kind(
475 |l| {
476 let mut bcx = bcx;
477 match l.appropriate_rvalue_mode(bcx.ccx()) {
478 ByRef => {
479 let scratch = rvalue_scratch_datum(bcx, l.ty, name);
480 bcx = l.store_to(bcx, scratch.val);
481 DatumBlock(bcx, scratch)
482 }
483 ByValue => {
484 let v = load(bcx, l.val, l.ty);
485 bcx = l.kind.post_store(bcx, l.val, l.ty);
486 DatumBlock(bcx, Datum(v, l.ty, Rvalue(ByValue)))
487 }
488 }
489 },
490 |r| DatumBlock(bcx, r))
491 }
492
493 }
494
495 /**
496 * Methods suitable only for lvalues. These include the various
497 * operations to extract components out of compound data structures,
498 * such as extracting the field from a struct or a particular element
499 * from an array.
500 */
501 impl Datum<Lvalue> {
502 pub fn to_llref(self) -> ValueRef {
503 /*!
504 * Converts a datum into a by-ref value. The datum type must
505 * be one which is always passed by reference.
506 */
507
508 self.val
509 }
510
511 pub fn get_element(&self,
512 ty: ty::t,
513 gep: |ValueRef| -> ValueRef)
514 -> Datum<Lvalue> {
515 Datum {
516 val: gep(self.val),
517 kind: Lvalue,
518 ty: ty,
519 }
520 }
521
522 pub fn get_vec_base_and_len<'a>(&self, bcx: &'a Block<'a>) -> (ValueRef, ValueRef) {
523 //! Converts a vector into the slice pair.
524
525 tvec::get_base_and_len(bcx, self.val, self.ty)
526 }
527 }
528
529 fn load<'a>(bcx: &'a Block<'a>, llptr: ValueRef, ty: ty::t) -> ValueRef {
530 /*!
531 * Private helper for loading from a by-ref datum. Handles various
532 * special cases where the type gives us better information about
533 * what we are loading.
534 */
535
536 if type_is_zero_size(bcx.ccx(), ty) {
537 C_undef(type_of::type_of(bcx.ccx(), ty))
538 } else if ty::type_is_bool(ty) {
539 LoadRangeAssert(bcx, llptr, 0, 2, lib::llvm::False)
540 } else if ty::type_is_char(ty) {
541 // a char is a unicode codepoint, and so takes values from 0
542 // to 0x10FFFF inclusive only.
543 LoadRangeAssert(bcx, llptr, 0, 0x10FFFF + 1, lib::llvm::False)
544 } else {
545 Load(bcx, llptr)
546 }
547 }
548
549 /**
550 * Generic methods applicable to any sort of datum.
551 */
552 impl<K:KindOps> Datum<K> {
553 pub fn to_expr_datum(self) -> Datum<Expr> {
554 let Datum { val, ty, kind } = self;
555 Datum { val: val, ty: ty, kind: kind.to_expr_kind() }
556 }
557
558 pub fn store_to<'a>(self,
559 bcx: &'a Block<'a>,
560 dst: ValueRef)
561 -> &'a Block<'a> {
562 /*!
563 * Moves or copies this value into a new home, as appropriate
564 * depending on the type of the datum. This method consumes
565 * the datum, since it would be incorrect to go on using the
566 * datum if the value represented is affine (and hence the value
567 * is moved).
568 */
569
570 self.shallow_copy(bcx, dst);
571
572 self.kind.post_store(bcx, self.val, self.ty)
573 }
574
575 fn shallow_copy<'a>(&self,
576 bcx: &'a Block<'a>,
577 dst: ValueRef)
578 -> &'a Block<'a> {
579 /*!
580 * Helper function that performs a shallow copy of this value
581 * into `dst`, which should be a pointer to a memory location
582 * suitable for `self.ty`. `dst` should contain uninitialized
583 * memory (either newly allocated, zeroed, or dropped).
584 *
585 * This function is private to datums because it leaves memory
586 * in an unstable state, where the source value has been
587 * copied but not zeroed. Public methods are `store_to` (if
588 * you no longer need the source value) or
589 * `shallow_copy_and_take` (if you wish the source value to
590 * remain valid).
591 */
592
593 let _icx = push_ctxt("copy_to_no_check");
594
595 if type_is_zero_size(bcx.ccx(), self.ty) {
596 return bcx;
597 }
598
599 if self.kind.is_by_ref() {
600 memcpy_ty(bcx, dst, self.val, self.ty);
601 } else {
602 Store(bcx, self.val, dst);
603 }
604
605 return bcx;
606 }
607
608 pub fn shallow_copy_and_take<'a>(&self,
609 bcx: &'a Block<'a>,
610 dst: ValueRef)
611 -> &'a Block<'a> {
612 /*!
613 * Copies the value into a new location and runs any necessary
614 * take glue on the new location. This function always
615 * preserves the existing datum as a valid value. Therefore,
616 * it does not consume `self` and, also, cannot be applied to
617 * affine values (since they must never be duplicated).
618 */
619
620 assert!(!ty::type_moves_by_default(bcx.tcx(), self.ty));
621 let mut bcx = bcx;
622 bcx = self.shallow_copy(bcx, dst);
623 glue::take_ty(bcx, dst, self.ty)
624 }
625
626 #[allow(dead_code)] // useful for debugging
627 pub fn to_str(&self, ccx: &CrateContext) -> ~str {
628 format!("Datum({}, {}, {:?})",
629 ccx.tn.val_to_str(self.val),
630 ty_to_str(ccx.tcx(), self.ty),
631 self.kind)
632 }
633
634 pub fn appropriate_rvalue_mode(&self, ccx: &CrateContext) -> RvalueMode {
635 /*! See the `appropriate_rvalue_mode()` function */
636
637 appropriate_rvalue_mode(ccx, self.ty)
638 }
639
640 pub fn to_llscalarish<'a>(self, bcx: &'a Block<'a>) -> ValueRef {
641 /*!
642 * Converts `self` into a by-value `ValueRef`. Consumes this
643 * datum (i.e., absolves you of responsibility to cleanup the
644 * value). For this to work, the value must be something
645 * scalar-ish (like an int or a pointer) which (1) does not
646 * require drop glue and (2) is naturally passed around by
647 * value, and not by reference.
648 */
649
650 assert!(!ty::type_needs_drop(bcx.tcx(), self.ty));
651 assert!(self.appropriate_rvalue_mode(bcx.ccx()) == ByValue);
652 if self.kind.is_by_ref() {
653 load(bcx, self.val, self.ty)
654 } else {
655 self.val
656 }
657 }
658
659 pub fn to_llbool<'a>(self, bcx: &'a Block<'a>) -> ValueRef {
660 assert!(ty::type_is_bool(self.ty) || ty::type_is_bot(self.ty))
661 let cond_val = self.to_llscalarish(bcx);
662 bool_to_i1(bcx, cond_val)
663 }
664 }
665
666 impl<'a, K:KindOps> DatumBlock<'a, K> {
667 pub fn to_expr_datumblock(self) -> DatumBlock<'a, Expr> {
668 DatumBlock(self.bcx, self.datum.to_expr_datum())
669 }
670 }
671
672 impl<'a> DatumBlock<'a, Expr> {
673 pub fn store_to_dest(self,
674 dest: expr::Dest,
675 expr_id: ast::NodeId) -> &'a Block<'a> {
676 let DatumBlock { bcx, datum } = self;
677 datum.store_to_dest(bcx, dest, expr_id)
678 }
679
680 pub fn to_llbool(self) -> Result<'a> {
681 let DatumBlock { datum, bcx } = self;
682 Result::new(bcx, datum.to_llbool(bcx))
683 }
684 }
librustc/middle/trans/datum.rs:176:1-176:1 -fn- definition:
fn add_rvalue_clean(mode: RvalueMode,
fcx: &FunctionContext,
scope: cleanup::ScopeId,
references:- 2304: add_rvalue_clean(self.kind.mode, fcx, scope, self.val, self.ty);
305: self.val
--
321: ByRef => {
322: add_rvalue_clean(ByRef, fcx, scope, self.val, self.ty);
323: DatumBlock(bcx, Datum(self.val, self.ty, Lvalue))
librustc/middle/trans/datum.rs:38:19-38:19 -struct- definition:
pub struct Datum<K> {
/// The llvm value. This is either a pointer to the Rust value or
/// the value itself, depending on `kind` below.
references:- 53librustc/middle/trans/expr.rs:
librustc/middle/trans/intrinsic.rs:
librustc/middle/trans/datum.rs:
librustc/middle/trans/callee.rs:
librustc/middle/trans/expr.rs:
librustc/middle/trans/common.rs:
librustc/middle/trans/base.rs:
librustc/middle/trans/_match.rs:
librustc/middle/trans/closure.rs:
librustc/middle/trans/meth.rs:
librustc/middle/trans/debuginfo.rs:
librustc/middle/trans/common.rs:
librustc/middle/trans/datum.rs:95:1-95:1 -fn- definition:
pub fn DatumBlock<'a, K>(bcx: &'a Block<'a>,
datum: Datum<K>)
-> DatumBlock<'a, K> {
references:- 28485: bcx = l.kind.post_store(bcx, l.val, l.ty);
486: DatumBlock(bcx, Datum(v, l.ty, Rvalue(ByValue)))
487: }
--
489: },
490: |r| DatumBlock(bcx, r))
491: }
--
667: pub fn to_expr_datumblock(self) -> DatumBlock<'a, Expr> {
668: DatumBlock(self.bcx, self.datum.to_expr_datum())
669: }
librustc/middle/trans/expr.rs:
496: let elt = PointerCast(bcx, elt, vt.llunit_ty.ptr_to());
497: DatumBlock(bcx, Datum(elt, vt.unit_ty, LvalueExpr))
498: }
--
846: let fn_ty = expr_ty(bcx, ref_expr);
847: DatumBlock(bcx, Datum(llfn, fn_ty, RvalueExpr(Rvalue(ByValue))))
848: }
--
1749: // owner (or, in the case of *T, by the user).
1750: DatumBlock(bcx, Datum(ptr, content_ty, LvalueExpr))
1751: }
librustc/middle/trans/closure.rs:
475: DatumBlock(bcx, scratch.to_expr_datum())
476: }
librustc/middle/trans/tvec.rs:
259: Some(expr::SaveIn(lldestval.val))).bcx;
260: return DatumBlock(bcx, lldestval).to_expr_datumblock();
261: }
librustc/middle/trans/expr.rs:
1655: // of type `&referent_ty`.
1656: DatumBlock(bcx, Datum(llref, ptr_ty, RvalueExpr(Rvalue(ByValue))))
1657: }
librustc/middle/trans/datum.rs:67:19-67:19 -struct- definition:
pub struct Lvalue;
pub struct Rvalue {
pub mode: RvalueMode
references:- 20233: impl KindOps for Lvalue {
234: fn post_store<'a>(&self,
--
386: #[allow(dead_code)] // potentially useful
387: pub fn assert_lvalue(self, bcx: &Block) -> Datum<Lvalue> {
388: /*!
--
513: gep: |ValueRef| -> ValueRef)
514: -> Datum<Lvalue> {
515: Datum {
librustc/middle/trans/callee.rs:
59: pub enum CalleeData {
60: Closure(Datum<Lvalue>),
librustc/middle/trans/expr.rs:
886: nid: ast::NodeId)
887: -> Datum<Lvalue> {
888: let datum = match table.find(&nid) {
librustc/middle/trans/common.rs:
206: pub type RvalueDatum = datum::Datum<datum::Rvalue>;
207: pub type LvalueDatum = datum::Datum<datum::Lvalue>;
librustc/middle/trans/base.rs:
1254: pub type RvalueDatum = datum::Datum<datum::Rvalue>;
1255: pub type LvalueDatum = datum::Datum<datum::Lvalue>;
librustc/middle/trans/_match.rs:
988: pat_id: ast::NodeId)
989: -> Datum<Lvalue> {
990: /*!
librustc/middle/trans/closure.rs:
102: action: freevars::CaptureMode,
103: datum: Datum<Lvalue>
104: }
librustc/middle/trans/debuginfo.rs:
485: span: Span,
486: datum: Datum<Lvalue>) {
487: if fn_should_be_ignored(bcx.fcx) {
librustc/middle/trans/datum.rs:
500: */
501: impl Datum<Lvalue> {
502: pub fn to_llref(self) -> ValueRef {
librustc/middle/trans/datum.rs:141:1-141:1 -fn- definition:
pub fn rvalue_scratch_datum(bcx: &Block,
ty: ty::t,
name: &str)
references:- 10478: ByRef => {
479: let scratch = rvalue_scratch_datum(bcx, l.ty, name);
480: bcx = l.store_to(bcx, scratch.val);
librustc/middle/trans/expr.rs:
244: let scratch = rvalue_scratch_datum(bcx, slice_ty, "__adjust");
245: Store(bcx, base, GEPi(bcx, scratch.val, [0u, abi::slice_elt_base]));
--
343: } else {
344: let scratch = rvalue_scratch_datum(bcx, ty, "");
345: bcx = trans_rvalue_dps_unadjusted(
librustc/middle/trans/_match.rs:
1035: ty::mt {ty: vt.unit_ty, mutbl: ast::MutImmutable});
1036: let scratch = rvalue_scratch_datum(bcx, slice_ty, "");
1037: Store(bcx, slice_begin,
librustc/middle/trans/closure.rs:
470: -> DatumBlock<'a, Expr> {
471: let scratch = rvalue_scratch_datum(bcx, closure_ty, "__adjust");
472: let wrapper = get_wrapper_for_bare_fn(bcx.ccx(), closure_ty, def, fn_ptr, true);
librustc/middle/trans/tvec.rs:
247: let typ = ty::mk_uniq(bcx.tcx(), ty::mk_str(bcx.tcx()));
248: let lldestval = rvalue_scratch_datum(bcx,
249: typ,
librustc/middle/trans/reflect.rs:
58: let str_ty = ty::mk_str_slice(bcx.tcx(), ty::ReStatic, ast::MutImmutable);
59: let scratch = rvalue_scratch_datum(bcx, str_ty, "");
60: let len = C_uint(bcx.ccx(), s.get().len());
librustc/middle/trans/datum.rs:
338: ByValue => {
339: let scratch = rvalue_scratch_datum(bcx, self.ty, "to_ref");
340: bcx = self.store_to(bcx, scratch.val);
librustc/middle/trans/datum.rs:55:1-55:1 -enum- definition:
pub enum Expr {
/// a fresh value that was produced and which has no cleanup yet
/// because it has not yet "landed" into its permanent home
references:- 52librustc/middle/trans/callee.rs:
librustc/middle/trans/expr.rs:
librustc/middle/trans/closure.rs:
librustc/middle/trans/tvec.rs:
librustc/middle/trans/meth.rs:
librustc/middle/trans/expr.rs:
librustc/middle/trans/datum.rs:73:1-73:1 -fn- definition:
pub fn Rvalue(m: RvalueMode) -> Rvalue {
Rvalue { mode: m }
}
references:- 10485: bcx = l.kind.post_store(bcx, l.val, l.ty);
486: DatumBlock(bcx, Datum(v, l.ty, Rvalue(ByValue)))
487: }
librustc/middle/trans/expr.rs:
1708: let ref_ty = ty::ty_fn_ret(monomorphize_type(bcx, method_ty));
1709: Datum(val, ref_ty, RvalueExpr(Rvalue(ByValue)))
1710: }
--
1811: RvalueExpr(Rvalue { mode: ByValue }) => {
1812: (datum.val, RvalueExpr(Rvalue(ByRef)))
1813: }
librustc/middle/trans/intrinsic.rs:
311: ty: tp_ty,
312: kind: Rvalue(mode)};
313: bcx = src.store_to(bcx, get_param(decl, first_real_arg));
librustc/middle/trans/expr.rs:
1808: RvalueExpr(Rvalue { mode: ByRef }) => {
1809: (Load(bcx, datum.val), RvalueExpr(Rvalue(ByRef)))
1810: }
librustc/middle/trans/datum.rs:187:1-187:1 -trait- definition:
pub trait KindOps {
/**
* Take appropriate action after the value in `datum` has been
references:- 6268: impl KindOps for Expr {
269: fn post_store<'a>(&self,
--
666: impl<'a, K:KindOps> DatumBlock<'a, K> {
667: pub fn to_expr_datumblock(self) -> DatumBlock<'a, Expr> {
librustc/middle/trans/datum.rs:50:1-50:1 -struct- definition:
pub struct DatumBlock<'a, K> {
pub bcx: &'a Block<'a>,
pub datum: Datum<K>,
references:- 52librustc/middle/trans/expr.rs:
librustc/middle/trans/datum.rs:
librustc/middle/trans/callee.rs:
librustc/middle/trans/expr.rs:
librustc/middle/trans/closure.rs:
librustc/middle/trans/tvec.rs:
librustc/middle/trans/datum.rs:
librustc/middle/trans/datum.rs:101:1-101:1 -fn- definition:
pub fn immediate_rvalue(val: ValueRef, ty: ty::t) -> Datum<Rvalue> {
return Datum(val, ty, Rvalue(ByValue));
}
references:- 2109: -> DatumBlock<'a, Rvalue> {
110: return DatumBlock(bcx, immediate_rvalue(val, ty))
111: }
librustc/middle/trans/expr.rs:
366: let llval = C_undef(type_of::type_of(bcx.ccx(), ty));
367: let datum = immediate_rvalue(llval, ty);
368: DatumBlock(bcx, datum.to_expr_datum())
librustc/middle/trans/datum.rs:91:1-91:1 -fn- definition:
pub fn Datum<K:KindOps>(val: ValueRef, ty: ty::t, kind: K) -> Datum<K> {
Datum { val: val, ty: ty, kind: kind }
}
references:- 23357: let llval = load(bcx, self.val, self.ty);
358: DatumBlock(bcx, Datum(llval, self.ty, Rvalue(ByValue)))
359: }
--
381: LvalueExpr => if_lvalue(Datum(val, ty, Lvalue)),
382: RvalueExpr(r) => if_rvalue(Datum(val, ty, r)),
383: }
--
485: bcx = l.kind.post_store(bcx, l.val, l.ty);
486: DatumBlock(bcx, Datum(v, l.ty, Rvalue(ByValue)))
487: }
librustc/middle/trans/expr.rs:
1655: // of type `&referent_ty`.
1656: DatumBlock(bcx, Datum(llref, ptr_ty, RvalueExpr(Rvalue(ByValue))))
1657: }
--
1749: // owner (or, in the case of *T, by the user).
1750: DatumBlock(bcx, Datum(ptr, content_ty, LvalueExpr))
1751: }
librustc/middle/trans/base.rs:
1270: };
1271: datum::Datum(llarg, arg_ty, arg_kind(fcx, arg_ty))
1272: }).collect()
librustc/middle/trans/_match.rs:
1292: let llval = Load(bcx, binding_info.llmatch); // get a T*
1293: let datum = Datum(llval, binding_info.ty, Lvalue);
1294: bcx = datum.store_to(bcx, lldest);
--
1330: let datum = Datum(llval, binding_info.ty, Lvalue);
1331: fcx.schedule_drop_mem(cleanup_scope, llval, binding_info.ty);
--
2175: // points at into the binding's stack slot.
2176: let d = Datum(val, ty, Lvalue);
2177: d.store_to(bcx, llval)
librustc/middle/trans/datum.rs:
102: pub fn immediate_rvalue(val: ValueRef, ty: ty::t) -> Datum<Rvalue> {
103: return Datum(val, ty, Rvalue(ByValue));
104: }
librustc/middle/trans/datum.rs:105:1-105:1 -fn- definition:
pub fn immediate_rvalue_bcx<'a>(bcx: &'a Block<'a>,
val: ValueRef,
ty: ty::t)
references:- 12librustc/middle/trans/expr.rs:
1344: immediate_rvalue_bcx(bcx, val, binop_ty).to_expr_datumblock()
1345: }
--
1598: };
1599: return immediate_rvalue_bcx(bcx, newval, t_out).to_expr_datumblock();
1600: }
librustc/middle/trans/tvec.rs:
301: immediate_rvalue_bcx(bcx, val, vec_ty).to_expr_datumblock()
302: }
librustc/middle/trans/expr.rs:
1148: };
1149: immediate_rvalue_bcx(bcx, llneg, un_ty).to_expr_datumblock()
1150: }
librustc/middle/trans/datum.rs:160:1-160:1 -fn- definition:
pub fn appropriate_rvalue_mode(ccx: &CrateContext, ty: ty::t) -> RvalueMode {
/*!
* Indicates the "appropriate" mode for this value,
references:- 2637: appropriate_rvalue_mode(ccx, self.ty)
638: }
librustc/middle/trans/intrinsic.rs:
308: let tp_ty = *substs.tys.get(0);
309: let mode = appropriate_rvalue_mode(ccx, tp_ty);
310: let src = Datum {val: get_param(decl, first_real_arg + 1u),
librustc/middle/trans/datum.rs:528:1-528:1 -fn- definition:
fn load<'a>(bcx: &'a Block<'a>, llptr: ValueRef, ty: ty::t) -> ValueRef {
/*!
* Private helper for loading from a by-ref datum. Handles various
references:- 3483: ByValue => {
484: let v = load(bcx, l.val, l.ty);
485: bcx = l.kind.post_store(bcx, l.val, l.ty);
--
652: if self.kind.is_by_ref() {
653: load(bcx, self.val, self.ty)
654: } else {
librustc/middle/trans/datum.rs:83:31-83:31 -enum- definition:
pub enum RvalueMode {
/// `val` is a pointer to the actual value (and thus has type *T)
ByRef,
references:- 1084: pub enum RvalueMode {
--
177: fn add_rvalue_clean(mode: RvalueMode,
178: fcx: &FunctionContext,
--
634: pub fn appropriate_rvalue_mode(&self, ccx: &CrateContext) -> RvalueMode {
635: /*! See the `appropriate_rvalue_mode()` function */
librustc/middle/trans/datum.rs:69:1-69:1 -struct- definition:
pub struct Rvalue {
pub mode: RvalueMode
}
references:- 2374: pub fn Rvalue(m: RvalueMode) -> Rvalue {
75: Rvalue { mode: m }
76: }
librustc/middle/trans/base.rs:
1248: datum::Rvalue {
1249: mode: if arg_is_indirect(cx.ccx, t) { ByRef } else { ByValue }
librustc/middle/trans/datum.rs:
467: name: &'static str)
468: -> DatumBlock<'a, Rvalue> {
469: /*!
librustc/middle/trans/expr.rs:
1807: }
1808: RvalueExpr(Rvalue { mode: ByRef }) => {
1809: (Load(bcx, datum.val), RvalueExpr(Rvalue(ByRef)))
1810: }
1811: RvalueExpr(Rvalue { mode: ByValue }) => {
1812: (datum.val, RvalueExpr(Rvalue(ByRef)))
librustc/middle/trans/common.rs:
205: // work around bizarre resolve errors
206: pub type RvalueDatum = datum::Datum<datum::Rvalue>;
207: pub type LvalueDatum = datum::Datum<datum::Lvalue>;
librustc/middle/trans/base.rs:
1253: // work around bizarre resolve errors
1254: pub type RvalueDatum = datum::Datum<datum::Rvalue>;
1255: pub type LvalueDatum = datum::Datum<datum::Lvalue>;
librustc/middle/trans/_match.rs:
2043: pat: @ast::Pat,
2044: arg: Datum<Rvalue>,
2045: arg_scope: cleanup::ScopeId)