]> git.lizzy.rs Git - rust.git/blob - src/librustc/middle/trans/datum.rs
rand: Use fill() instead of read()
[rust.git] / src / librustc / middle / trans / datum.rs
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::trans::write_guard;
28 use middle::ty;
29 use util::ppaux::{ty_to_str};
30
31 use syntax::ast;
32 use syntax::codemap::Span;
33
34 /**
35  * A `Datum` encapsulates the result of evaluating an expression.  It
36  * describes where the value is stored, what Rust type the value has,
37  * whether it is addressed by reference, and so forth. Please refer
38  * the section on datums in `doc.rs` for more details.
39  */
40 #[deriving(Clone)]
41 pub struct Datum<K> {
42     /// The llvm value.  This is either a pointer to the Rust value or
43     /// the value itself, depending on `kind` below.
44     val: ValueRef,
45
46     /// The rust type of the value.
47     ty: ty::t,
48
49     /// Indicates whether this is by-ref or by-value.
50     kind: K,
51 }
52
53 pub struct DatumBlock<'a, K> {
54     bcx: &'a Block<'a>,
55     datum: Datum<K>,
56 }
57
58 pub enum Expr {
59     /// a fresh value that was produced and which has no cleanup yet
60     /// because it has not yet "landed" into its permanent home
61     RvalueExpr(Rvalue),
62
63     /// `val` is a pointer into memory for which a cleanup is scheduled
64     /// (and thus has type *T). If you move out of an Lvalue, you must
65     /// zero out the memory (FIXME #5016).
66     LvalueExpr,
67 }
68
69 #[deriving(Clone)]
70 pub struct Lvalue;
71
72 pub struct Rvalue {
73     mode: RvalueMode
74 }
75
76 pub fn Rvalue(m: RvalueMode) -> Rvalue {
77     Rvalue { mode: m }
78 }
79
80 // Make Datum linear for more type safety.
81 impl Drop for Rvalue {
82     fn drop(&mut self) { }
83 }
84
85 #[deriving(Eq, Hash)]
86 pub enum RvalueMode {
87     /// `val` is a pointer to the actual value (and thus has type *T)
88     ByRef,
89
90     /// `val` is the actual value (*only used for immediates* like ints, ptrs)
91     ByValue,
92 }
93
94 pub fn Datum<K:KindOps>(val: ValueRef, ty: ty::t, kind: K) -> Datum<K> {
95     Datum { val: val, ty: ty, kind: kind }
96 }
97
98 pub fn DatumBlock<'a, K>(bcx: &'a Block<'a>,
99                          datum: Datum<K>)
100                          -> DatumBlock<'a, K> {
101     DatumBlock { bcx: bcx, datum: datum }
102 }
103
104 pub fn immediate_rvalue(val: ValueRef, ty: ty::t) -> Datum<Rvalue> {
105     return Datum(val, ty, Rvalue(ByValue));
106 }
107
108 pub fn immediate_rvalue_bcx<'a>(bcx: &'a Block<'a>,
109                                 val: ValueRef,
110                                 ty: ty::t)
111                                 -> DatumBlock<'a, Rvalue> {
112     return DatumBlock(bcx, immediate_rvalue(val, ty))
113 }
114
115
116 pub fn lvalue_scratch_datum<'a, A>(bcx: &'a Block<'a>,
117                                    ty: ty::t,
118                                    name: &str,
119                                    zero: bool,
120                                    scope: cleanup::ScopeId,
121                                    arg: A,
122                                    populate: |A, &'a Block<'a>, ValueRef|
123                                              -> &'a Block<'a>)
124                                    -> DatumBlock<'a, Lvalue> {
125     /*!
126      * Allocates temporary space on the stack using alloca() and
127      * returns a by-ref Datum pointing to it. The memory will be
128      * dropped upon exit from `scope`. The callback `populate` should
129      * initialize the memory. If `zero` is true, the space will be
130      * zeroed when it is allocated; this is not necessary unless `bcx`
131      * does not dominate the end of `scope`.
132      */
133
134     let llty = type_of::type_of(bcx.ccx(), ty);
135     let scratch = alloca_maybe_zeroed(bcx, llty, name, zero);
136
137     // Subtle. Populate the scratch memory *before* scheduling cleanup.
138     let bcx = populate(arg, bcx, scratch);
139     bcx.fcx.schedule_drop_mem(scope, scratch, ty);
140
141     DatumBlock(bcx, Datum(scratch, ty, Lvalue))
142 }
143
144 pub fn rvalue_scratch_datum(bcx: &Block,
145                             ty: ty::t,
146                             name: &str)
147                             -> Datum<Rvalue> {
148     /*!
149      * Allocates temporary space on the stack using alloca() and
150      * returns a by-ref Datum pointing to it.  If `zero` is true, the
151      * space will be zeroed when it is allocated; this is normally not
152      * necessary, but in the case of automatic rooting in match
153      * statements it is possible to have temporaries that may not get
154      * initialized if a certain arm is not taken, so we must zero
155      * them. You must arrange any cleanups etc yourself!
156      */
157
158     let llty = type_of::type_of(bcx.ccx(), ty);
159     let scratch = alloca_maybe_zeroed(bcx, llty, name, false);
160     Datum(scratch, ty, Rvalue(ByRef))
161 }
162
163 pub fn is_by_value_type(ccx: &CrateContext, ty: ty::t) -> bool {
164     appropriate_rvalue_mode(ccx, ty) == ByValue
165 }
166
167 pub fn appropriate_rvalue_mode(ccx: &CrateContext, ty: ty::t) -> RvalueMode {
168     /*!
169      * Indicates the "appropriate" mode for this value,
170      * which is either by ref or by value, depending
171      * on whether type is immediate or not.
172      */
173
174     if type_is_zero_size(ccx, ty) {
175         ByValue
176     } else if type_is_immediate(ccx, ty) {
177         ByValue
178     } else {
179         ByRef
180     }
181 }
182
183 fn add_rvalue_clean(mode: RvalueMode,
184                     fcx: &FunctionContext,
185                     scope: cleanup::ScopeId,
186                     val: ValueRef,
187                     ty: ty::t) {
188     match mode {
189         ByValue => { fcx.schedule_drop_immediate(scope, val, ty); }
190         ByRef => { fcx.schedule_drop_mem(scope, val, ty); }
191     }
192 }
193
194 pub trait KindOps {
195
196     /**
197      * Take appropriate action after the value in `datum` has been
198      * stored to a new location.
199      */
200     fn post_store<'a>(&self,
201                       bcx: &'a Block<'a>,
202                       val: ValueRef,
203                       ty: ty::t)
204                       -> &'a Block<'a>;
205
206     /**
207      * True if this mode is a reference mode, meaning that the datum's
208      * val field is a pointer to the actual value
209      */
210     fn is_by_ref(&self) -> bool;
211
212     /**
213      * Converts to an Expr kind
214      */
215     fn to_expr_kind(self) -> Expr;
216
217 }
218
219 impl KindOps for Rvalue {
220     fn post_store<'a>(&self,
221                       bcx: &'a Block<'a>,
222                       _val: ValueRef,
223                       _ty: ty::t)
224                       -> &'a Block<'a> {
225         // No cleanup is scheduled for an rvalue, so we don't have
226         // to do anything after a move to cancel or duplicate it.
227         bcx
228     }
229
230     fn is_by_ref(&self) -> bool {
231         self.mode == ByRef
232     }
233
234     fn to_expr_kind(self) -> Expr {
235         RvalueExpr(self)
236     }
237 }
238
239 impl KindOps for Lvalue {
240     fn post_store<'a>(&self,
241                       bcx: &'a Block<'a>,
242                       val: ValueRef,
243                       ty: ty::t)
244                       -> &'a Block<'a> {
245         /*!
246          * If an lvalue is moved, we must zero out the memory in which
247          * it resides so as to cancel cleanup. If an @T lvalue is
248          * copied, we must increment the reference count.
249          */
250
251         if ty::type_needs_drop(bcx.tcx(), ty) {
252             if ty::type_moves_by_default(bcx.tcx(), ty) {
253                 // cancel cleanup of affine values by zeroing out
254                 let () = zero_mem(bcx, val, ty);
255                 bcx
256             } else {
257                 // incr. refcount for @T or newtype'd @T
258                 glue::take_ty(bcx, val, ty)
259             }
260         } else {
261             bcx
262         }
263     }
264
265     fn is_by_ref(&self) -> bool {
266         true
267     }
268
269     fn to_expr_kind(self) -> Expr {
270         LvalueExpr
271     }
272 }
273
274 impl KindOps for Expr {
275     fn post_store<'a>(&self,
276                       bcx: &'a Block<'a>,
277                       val: ValueRef,
278                       ty: ty::t)
279                       -> &'a Block<'a> {
280         match *self {
281             LvalueExpr => Lvalue.post_store(bcx, val, ty),
282             RvalueExpr(ref r) => r.post_store(bcx, val, ty),
283         }
284     }
285
286     fn is_by_ref(&self) -> bool {
287         match *self {
288             LvalueExpr => Lvalue.is_by_ref(),
289             RvalueExpr(ref r) => r.is_by_ref()
290         }
291     }
292
293     fn to_expr_kind(self) -> Expr {
294         self
295     }
296 }
297
298 impl Datum<Rvalue> {
299     pub fn add_clean(self,
300                      fcx: &FunctionContext,
301                      scope: cleanup::ScopeId)
302                      -> ValueRef {
303         /*!
304          * Schedules a cleanup for this datum in the given scope.
305          * That means that this datum is no longer an rvalue datum;
306          * hence, this function consumes the datum and returns the
307          * contained ValueRef.
308          */
309
310         add_rvalue_clean(self.kind.mode, fcx, scope, self.val, self.ty);
311         self.val
312     }
313
314     pub fn to_lvalue_datum_in_scope<'a>(self,
315                                         bcx: &'a Block<'a>,
316                                         name: &str,
317                                         scope: cleanup::ScopeId)
318                                         -> DatumBlock<'a, Lvalue> {
319         /*!
320          * Returns an lvalue datum (that is, a by ref datum with
321          * cleanup scheduled). If `self` is not already an lvalue,
322          * cleanup will be scheduled in the temporary scope for `expr_id`.
323          */
324         let fcx = bcx.fcx;
325
326         match self.kind.mode {
327             ByRef => {
328                 add_rvalue_clean(ByRef, fcx, scope, self.val, self.ty);
329                 DatumBlock(bcx, Datum(self.val, self.ty, Lvalue))
330             }
331
332             ByValue => {
333                 lvalue_scratch_datum(
334                     bcx, self.ty, name, false, scope, self,
335                     |this, bcx, llval| this.store_to(bcx, llval))
336             }
337         }
338     }
339
340     pub fn to_ref_datum<'a>(self, bcx: &'a Block<'a>) -> DatumBlock<'a, Rvalue> {
341         let mut bcx = bcx;
342         match self.kind.mode {
343             ByRef => DatumBlock(bcx, self),
344             ByValue => {
345                 let scratch = rvalue_scratch_datum(bcx, self.ty, "to_ref");
346                 bcx = self.store_to(bcx, scratch.val);
347                 DatumBlock(bcx, scratch)
348             }
349         }
350     }
351
352     pub fn to_appropriate_datum<'a>(self,
353                                     bcx: &'a Block<'a>)
354                                     -> DatumBlock<'a, Rvalue> {
355         match self.appropriate_rvalue_mode(bcx.ccx()) {
356             ByRef => {
357                 self.to_ref_datum(bcx)
358             }
359             ByValue => {
360                 match self.kind.mode {
361                     ByValue => DatumBlock(bcx, self),
362                     ByRef => {
363                         let llval = load(bcx, self.val, self.ty);
364                         DatumBlock(bcx, Datum(llval, self.ty, Rvalue(ByValue)))
365                     }
366                 }
367             }
368         }
369     }
370 }
371
372 /**
373  * Methods suitable for "expr" datums that could be either lvalues or
374  * rvalues. These include coercions into lvalues/rvalues but also a number
375  * of more general operations. (Some of those operations could be moved to
376  * the more general `impl<K> Datum<K>`, but it's convenient to have them
377  * here since we can `match self.kind` rather than having to implement
378  * generic methods in `KindOps`.)
379  */
380 impl Datum<Expr> {
381     fn match_kind<R>(self,
382                      if_lvalue: |Datum<Lvalue>| -> R,
383                      if_rvalue: |Datum<Rvalue>| -> R)
384                      -> R {
385         let Datum { val, ty, kind } = self;
386         match kind {
387             LvalueExpr => if_lvalue(Datum(val, ty, Lvalue)),
388             RvalueExpr(r) => if_rvalue(Datum(val, ty, r)),
389         }
390     }
391
392     pub fn is_by_ref(&self) -> bool {
393         self.kind.is_by_ref()
394     }
395
396     pub fn assert_lvalue(self, bcx: &Block) -> Datum<Lvalue> {
397         /*!
398          * Asserts that this datum *is* an lvalue and returns it.
399          */
400
401         self.match_kind(
402             |d| d,
403             |_| bcx.sess().bug("assert_lvalue given rvalue"))
404     }
405
406     pub fn assert_rvalue(self, bcx: &Block) -> Datum<Rvalue> {
407         /*!
408          * Asserts that this datum *is* an lvalue and returns it.
409          */
410
411         self.match_kind(
412             |_| bcx.sess().bug("assert_rvalue given lvalue"),
413             |r| r)
414     }
415
416     pub fn store_to_dest<'a>(self,
417                              bcx: &'a Block<'a>,
418                              dest: expr::Dest,
419                              expr_id: ast::NodeId)
420                              -> &'a Block<'a> {
421         match dest {
422             expr::Ignore => {
423                 self.add_clean_if_rvalue(bcx, expr_id);
424                 bcx
425             }
426             expr::SaveIn(addr) => {
427                 self.store_to(bcx, addr)
428             }
429         }
430     }
431
432     pub fn add_clean_if_rvalue<'a>(self,
433                                    bcx: &'a Block<'a>,
434                                    expr_id: ast::NodeId) {
435         /*!
436          * Arranges cleanup for `self` if it is an rvalue. Use when
437          * you are done working with a value that may need drop.
438          */
439
440         self.match_kind(
441             |_| { /* Nothing to do, cleanup already arranged */ },
442             |r| {
443                 let scope = cleanup::temporary_scope(bcx.tcx(), expr_id);
444                 r.add_clean(bcx.fcx, scope);
445             })
446     }
447
448     pub fn clean<'a>(self,
449                      bcx: &'a Block<'a>,
450                      name: &'static str,
451                      expr_id: ast::NodeId)
452                      -> &'a Block<'a> {
453         /*!
454          * Ensures that `self` will get cleaned up, if it is not an lvalue
455          * already.
456          */
457
458         self.to_lvalue_datum(bcx, name, expr_id).bcx
459     }
460
461     pub fn to_lvalue_datum<'a>(self,
462                                bcx: &'a Block<'a>,
463                                name: &str,
464                                expr_id: ast::NodeId)
465                                -> DatumBlock<'a, Lvalue> {
466         self.match_kind(
467             |l| DatumBlock(bcx, l),
468             |r| {
469                 let scope = cleanup::temporary_scope(bcx.tcx(), expr_id);
470                 r.to_lvalue_datum_in_scope(bcx, name, scope)
471             })
472     }
473
474     pub fn to_rvalue_datum<'a>(self,
475                                bcx: &'a Block<'a>,
476                                name: &'static str)
477                                -> DatumBlock<'a, Rvalue> {
478         /*!
479          * Ensures that we have an rvalue datum (that is, a datum with
480          * no cleanup scheduled).
481          */
482
483         self.match_kind(
484             |l| {
485                 let mut bcx = bcx;
486                 match l.appropriate_rvalue_mode(bcx.ccx()) {
487                     ByRef => {
488                         let scratch = rvalue_scratch_datum(bcx, l.ty, name);
489                         bcx = l.store_to(bcx, scratch.val);
490                         DatumBlock(bcx, scratch)
491                     }
492                     ByValue => {
493                         let v = load(bcx, l.val, l.ty);
494                         bcx = l.kind.post_store(bcx, l.val, l.ty);
495                         DatumBlock(bcx, Datum(v, l.ty, Rvalue(ByValue)))
496                     }
497                 }
498             },
499             |r| DatumBlock(bcx, r))
500     }
501
502 }
503
504 /**
505  * Methods suitable only for lvalues. These include the various
506  * operations to extract components out of compound data structures,
507  * such as extracting the field from a struct or a particular element
508  * from an array.
509  */
510 impl Datum<Lvalue> {
511     pub fn to_llref(self) -> ValueRef {
512         /*!
513          * Converts a datum into a by-ref value. The datum type must
514          * be one which is always passed by reference.
515          */
516
517         self.val
518     }
519
520     pub fn get_element(&self,
521                        ty: ty::t,
522                        gep: |ValueRef| -> ValueRef)
523                        -> Datum<Lvalue> {
524         Datum {
525             val: gep(self.val),
526             kind: Lvalue,
527             ty: ty,
528         }
529     }
530
531     pub fn get_vec_base_and_len<'a>(&self, bcx: &'a Block<'a>) -> (ValueRef, ValueRef) {
532         //! Converts a vector into the slice pair.
533
534         tvec::get_base_and_len(bcx, self.val, self.ty)
535     }
536 }
537
538 fn load<'a>(bcx: &'a Block<'a>, llptr: ValueRef, ty: ty::t) -> ValueRef {
539     /*!
540      * Private helper for loading from a by-ref datum. Handles various
541      * special cases where the type gives us better information about
542      * what we are loading.
543      */
544
545     if type_is_zero_size(bcx.ccx(), ty) {
546         C_undef(type_of::type_of(bcx.ccx(), ty))
547     } else if ty::type_is_bool(ty) {
548         LoadRangeAssert(bcx, llptr, 0, 2, lib::llvm::False)
549     } else if ty::type_is_char(ty) {
550         // a char is a unicode codepoint, and so takes values from 0
551         // to 0x10FFFF inclusive only.
552         LoadRangeAssert(bcx, llptr, 0, 0x10FFFF + 1, lib::llvm::False)
553     } else {
554         Load(bcx, llptr)
555     }
556 }
557
558 /**
559  * Generic methods applicable to any sort of datum.
560  */
561 impl<K:KindOps> Datum<K> {
562     pub fn to_expr_datum(self) -> Datum<Expr> {
563         let Datum { val, ty, kind } = self;
564         Datum { val: val, ty: ty, kind: kind.to_expr_kind() }
565     }
566
567     pub fn store_to<'a>(self,
568                         bcx: &'a Block<'a>,
569                         dst: ValueRef)
570                         -> &'a Block<'a> {
571         /*!
572          * Moves or copies this value into a new home, as appropriate
573          * depending on the type of the datum. This method consumes
574          * the datum, since it would be incorrect to go on using the
575          * datum if the value represented is affine (and hence the value
576          * is moved).
577          */
578
579         self.shallow_copy(bcx, dst);
580
581         self.kind.post_store(bcx, self.val, self.ty)
582     }
583
584     fn shallow_copy<'a>(&self,
585                         bcx: &'a Block<'a>,
586                         dst: ValueRef)
587                         -> &'a Block<'a> {
588         /*!
589          * Helper function that performs a shallow copy of this value
590          * into `dst`, which should be a pointer to a memory location
591          * suitable for `self.ty`. `dst` should contain uninitialized
592          * memory (either newly allocated, zeroed, or dropped).
593          *
594          * This function is private to datums because it leaves memory
595          * in an unstable state, where the source value has been
596          * copied but not zeroed. Public methods are `store_to` (if
597          * you no longer need the source value) or
598          * `shallow_copy_and_take` (if you wish the source value to
599          * remain valid).
600          */
601
602         let _icx = push_ctxt("copy_to_no_check");
603
604         if type_is_zero_size(bcx.ccx(), self.ty) {
605             return bcx;
606         }
607
608         if self.kind.is_by_ref() {
609             memcpy_ty(bcx, dst, self.val, self.ty);
610         } else {
611             Store(bcx, self.val, dst);
612         }
613
614         return bcx;
615     }
616
617     pub fn shallow_copy_and_take<'a>(&self,
618                                      bcx: &'a Block<'a>,
619                                      dst: ValueRef)
620                                      -> &'a Block<'a> {
621         /*!
622          * Copies the value into a new location and runs any necessary
623          * take glue on the new location. This function always
624          * preserves the existing datum as a valid value. Therefore,
625          * it does not consume `self` and, also, cannot be applied to
626          * affine values (since they must never be duplicated).
627          */
628
629         assert!(!ty::type_moves_by_default(bcx.tcx(), self.ty));
630         let mut bcx = bcx;
631         bcx = self.shallow_copy(bcx, dst);
632         glue::take_ty(bcx, dst, self.ty)
633     }
634
635     pub fn to_str(&self, ccx: &CrateContext) -> ~str {
636         format!("Datum({}, {}, {:?})",
637              ccx.tn.val_to_str(self.val),
638              ty_to_str(ccx.tcx(), self.ty),
639              self.kind)
640     }
641
642     pub fn appropriate_rvalue_mode(&self, ccx: &CrateContext) -> RvalueMode {
643         /*! See the `appropriate_rvalue_mode()` function */
644
645         appropriate_rvalue_mode(ccx, self.ty)
646     }
647
648     pub fn root_and_write_guard<'a>(
649                                 &self,
650                                 bcx: &'a Block<'a>,
651                                 span: Span,
652                                 expr_id: ast::NodeId,
653                                 derefs: uint)
654                                 -> &'a Block<'a> {
655         write_guard::root_and_write_guard(self, bcx, span, expr_id, derefs)
656     }
657
658     pub fn to_llscalarish<'a>(self, bcx: &'a Block<'a>) -> ValueRef {
659         /*!
660          * Converts `self` into a by-value `ValueRef`. Consumes this
661          * datum (i.e., absolves you of responsibility to cleanup the
662          * value). For this to work, the value must be something
663          * scalar-ish (like an int or a pointer) which (1) does not
664          * require drop glue and (2) is naturally passed around by
665          * value, and not by reference.
666          */
667
668         assert!(!ty::type_needs_drop(bcx.tcx(), self.ty));
669         assert!(self.appropriate_rvalue_mode(bcx.ccx()) == ByValue);
670         if self.kind.is_by_ref() {
671             load(bcx, self.val, self.ty)
672         } else {
673             self.val
674         }
675     }
676
677     pub fn to_llbool<'a>(self, bcx: &'a Block<'a>) -> ValueRef {
678         assert!(ty::type_is_bool(self.ty) || ty::type_is_bot(self.ty))
679         let cond_val = self.to_llscalarish(bcx);
680         bool_to_i1(bcx, cond_val)
681     }
682 }
683
684 impl<'a, K:KindOps> DatumBlock<'a, K> {
685     pub fn to_expr_datumblock(self) -> DatumBlock<'a, Expr> {
686         DatumBlock(self.bcx, self.datum.to_expr_datum())
687     }
688 }
689
690 impl<'a> DatumBlock<'a, Expr> {
691     pub fn assert_by_ref(self) -> DatumBlock<'a, Expr> {
692         assert!(self.datum.kind.is_by_ref());
693         self
694     }
695
696     pub fn store_to(self, dst: ValueRef) -> &'a Block<'a> {
697         let DatumBlock { bcx, datum } = self;
698         datum.store_to(bcx, dst)
699     }
700
701     pub fn store_to_dest(self,
702                          dest: expr::Dest,
703                          expr_id: ast::NodeId) -> &'a Block<'a> {
704         let DatumBlock { bcx, datum } = self;
705         datum.store_to_dest(bcx, dest, expr_id)
706     }
707
708     pub fn shallow_copy(self, dst: ValueRef) -> &'a Block<'a> {
709         self.datum.shallow_copy(self.bcx, dst)
710     }
711
712     pub fn ccx(&self) -> &'a CrateContext {
713         self.bcx.ccx()
714     }
715
716     pub fn tcx(&self) -> &'a ty::ctxt {
717         self.bcx.tcx()
718     }
719
720     pub fn to_str(&self) -> ~str {
721         self.datum.to_str(self.ccx())
722     }
723
724     pub fn to_llbool(self) -> Result<'a> {
725         let DatumBlock { datum, bcx } = self;
726         rslt(bcx, datum.to_llbool(bcx))
727     }
728 }