(index<- )        ./librustc/middle/trans/datum.rs

    git branch:    * master           5200215 auto merge of #14035 : alexcrichton/rust/experimental, r=huonw
    modified:    Fri May  9 13:02:28 2014
   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(mRvalueMode) -> 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>(valValueRef, tyty::t, kindK) -> Datum<K> {
  93      Datum { val: val, ty: ty, kind: kind }
  94  }
  95  
  96  pub fn DatumBlock<'a, K>(bcx: &'a Block<'a>,
  97                           datumDatum<K>)
  98                           -> DatumBlock<'a, K> {
  99      DatumBlock { bcx: bcx, datum: datum }
 100  }
 101  
 102  pub fn immediate_rvalue(valValueRef, tyty::t) -> Datum<Rvalue> {
 103      return Datum(val, ty, Rvalue(ByValue));
 104  }
 105  
 106  pub fn immediate_rvalue_bcx<'a>(bcx: &'a Block<'a>,
 107                                  valValueRef,
 108                                  tyty::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                                     tyty::t,
 116                                     name: &str,
 117                                     zero: bool,
 118                                     scopecleanup::ScopeId,
 119                                     argA,
 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                              tyty::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, tyty::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(modeRvalueMode,
 178                      fcx: &FunctionContext,
 179                      scopecleanup::ScopeId,
 180                      valValueRef,
 181                      tyty::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                        _valValueRef,
 217                        _tyty::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                        valValueRef,
 237                        tyty::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                        valValueRef,
 272                        tyty::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                       scopecleanup::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                                          scopecleanup::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                               destexpr::Dest,
 410                               expr_idast::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_idast::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_idast::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_idast::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                         tyty::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>, llptrValueRef, tyty::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                          dstValueRef)
 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                          dstValueRef)
 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                                       dstValueRef)
 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                           destexpr::Dest,
 675                           expr_idast::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:- 2
304:         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:- 53
librustc/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:- 28
485:                         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:- 20
233: 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:- 10
478:                     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:- 52
librustc/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:- 10
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:
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:- 6
268: 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:- 52
librustc/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:- 2
109:                                 -> 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:- 23
357:                         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:- 12
librustc/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:- 2
637:         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:- 3
483:                     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:- 10
84: 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:- 23
74: 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)