]> git.lizzy.rs Git - rust.git/blob - src/librustc/middle/trans/common.rs
auto merge of #15061 : pnkfelix/rust/fsk-fix-issue-10846, r=nikomatsakis
[rust.git] / src / librustc / middle / trans / common.rs
1 // Copyright 2012-2014 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 #![allow(non_camel_case_types, non_snake_case_functions)]
12
13 //! Code that is useful in various trans modules.
14
15 use driver::session::Session;
16 use lib::llvm::{ValueRef, BasicBlockRef, BuilderRef};
17 use lib::llvm::{True, False, Bool};
18 use lib::llvm::llvm;
19 use lib;
20 use middle::def;
21 use middle::lang_items::LangItem;
22 use middle::subst;
23 use middle::subst::Subst;
24 use middle::trans::build;
25 use middle::trans::cleanup;
26 use middle::trans::datum;
27 use middle::trans::debuginfo;
28 use middle::trans::type_::Type;
29 use middle::ty;
30 use middle::typeck;
31 use util::ppaux::Repr;
32 use util::nodemap::NodeMap;
33
34 use arena::TypedArena;
35 use std::collections::HashMap;
36 use libc::{c_uint, c_longlong, c_ulonglong, c_char};
37 use std::c_str::ToCStr;
38 use std::cell::{Cell, RefCell};
39 use std::vec::Vec;
40 use syntax::ast::Ident;
41 use syntax::ast;
42 use syntax::ast_map::{PathElem, PathName};
43 use syntax::codemap::Span;
44 use syntax::parse::token::InternedString;
45 use syntax::parse::token;
46
47 pub use middle::trans::context::CrateContext;
48
49 fn type_is_newtype_immediate(ccx: &CrateContext, ty: ty::t) -> bool {
50     match ty::get(ty).sty {
51         ty::ty_struct(def_id, ref substs) => {
52             let fields = ty::struct_fields(ccx.tcx(), def_id, substs);
53             fields.len() == 1 &&
54                 fields.get(0).ident.name ==
55                     token::special_idents::unnamed_field.name &&
56                 type_is_immediate(ccx, fields.get(0).mt.ty)
57         }
58         _ => false
59     }
60 }
61
62 pub fn type_is_immediate(ccx: &CrateContext, ty: ty::t) -> bool {
63     use middle::trans::machine::llsize_of_alloc;
64     use middle::trans::type_of::sizing_type_of;
65     let tcx = ccx.tcx();
66     let simple = ty::type_is_scalar(ty) || ty::type_is_boxed(ty) ||
67         ty::type_is_unique(ty) || ty::type_is_region_ptr(ty) ||
68         type_is_newtype_immediate(ccx, ty) || ty::type_is_bot(ty) ||
69         ty::type_is_simd(tcx, ty);
70     if simple && !ty::type_is_trait(ty) {
71         return true;
72     }
73     match ty::get(ty).sty {
74         ty::ty_bot => true,
75         ty::ty_struct(..) | ty::ty_enum(..) | ty::ty_tup(..) => {
76             let llty = sizing_type_of(ccx, ty);
77             llsize_of_alloc(ccx, llty) <= llsize_of_alloc(ccx, ccx.int_type)
78         }
79         _ => type_is_zero_size(ccx, ty)
80     }
81 }
82
83 pub fn type_is_zero_size(ccx: &CrateContext, ty: ty::t) -> bool {
84     /*!
85      * Identify types which have size zero at runtime.
86      */
87
88     use middle::trans::machine::llsize_of_alloc;
89     use middle::trans::type_of::sizing_type_of;
90     let llty = sizing_type_of(ccx, ty);
91     llsize_of_alloc(ccx, llty) == 0
92 }
93
94 pub fn return_type_is_void(ccx: &CrateContext, ty: ty::t) -> bool {
95     /*!
96      * Identifies types which we declare to be equivalent to `void`
97      * in C for the purpose of function return types. These are
98      * `()`, bot, and uninhabited enums. Note that all such types
99      * are also zero-size, but not all zero-size types use a `void`
100      * return type (in order to aid with C ABI compatibility).
101      */
102
103     ty::type_is_nil(ty) || ty::type_is_bot(ty) || ty::type_is_empty(ccx.tcx(), ty)
104 }
105
106 /// Generates a unique symbol based off the name given. This is used to create
107 /// unique symbols for things like closures.
108 pub fn gensym_name(name: &str) -> PathElem {
109     let num = token::gensym(name);
110     // use one colon which will get translated to a period by the mangler, and
111     // we're guaranteed that `num` is globally unique for this crate.
112     PathName(token::gensym(format!("{}:{}", name, num).as_slice()))
113 }
114
115 pub struct tydesc_info {
116     pub ty: ty::t,
117     pub tydesc: ValueRef,
118     pub size: ValueRef,
119     pub align: ValueRef,
120     pub name: ValueRef,
121     pub visit_glue: Cell<Option<ValueRef>>,
122 }
123
124 /*
125  * A note on nomenclature of linking: "extern", "foreign", and "upcall".
126  *
127  * An "extern" is an LLVM symbol we wind up emitting an undefined external
128  * reference to. This means "we don't have the thing in this compilation unit,
129  * please make sure you link it in at runtime". This could be a reference to
130  * C code found in a C library, or rust code found in a rust crate.
131  *
132  * Most "externs" are implicitly declared (automatically) as a result of a
133  * user declaring an extern _module_ dependency; this causes the rust driver
134  * to locate an extern crate, scan its compilation metadata, and emit extern
135  * declarations for any symbols used by the declaring crate.
136  *
137  * A "foreign" is an extern that references C (or other non-rust ABI) code.
138  * There is no metadata to scan for extern references so in these cases either
139  * a header-digester like bindgen, or manual function prototypes, have to
140  * serve as declarators. So these are usually given explicitly as prototype
141  * declarations, in rust code, with ABI attributes on them noting which ABI to
142  * link via.
143  *
144  * An "upcall" is a foreign call generated by the compiler (not corresponding
145  * to any user-written call in the code) into the runtime library, to perform
146  * some helper task such as bringing a task to life, allocating memory, etc.
147  *
148  */
149
150 pub struct NodeInfo {
151     pub id: ast::NodeId,
152     pub span: Span,
153 }
154
155 pub fn expr_info(expr: &ast::Expr) -> NodeInfo {
156     NodeInfo { id: expr.id, span: expr.span }
157 }
158
159 pub struct BuilderRef_res {
160     pub b: BuilderRef,
161 }
162
163 impl Drop for BuilderRef_res {
164     fn drop(&mut self) {
165         unsafe {
166             llvm::LLVMDisposeBuilder(self.b);
167         }
168     }
169 }
170
171 pub fn BuilderRef_res(b: BuilderRef) -> BuilderRef_res {
172     BuilderRef_res {
173         b: b
174     }
175 }
176
177 pub type ExternMap = HashMap<String, ValueRef>;
178
179 // Here `self_ty` is the real type of the self parameter to this method. It
180 // will only be set in the case of default methods.
181 pub struct param_substs {
182     pub substs: subst::Substs,
183     pub vtables: typeck::vtable_res,
184 }
185
186 impl param_substs {
187     pub fn empty() -> param_substs {
188         param_substs {
189             substs: subst::Substs::trans_empty(),
190             vtables: subst::VecPerParamSpace::empty(),
191         }
192     }
193
194     pub fn validate(&self) {
195         assert!(self.substs.types.all(|t| !ty::type_needs_infer(*t)));
196     }
197 }
198
199 fn param_substs_to_str(this: &param_substs, tcx: &ty::ctxt) -> String {
200     format!("param_substs({})", this.substs.repr(tcx))
201 }
202
203 impl Repr for param_substs {
204     fn repr(&self, tcx: &ty::ctxt) -> String {
205         param_substs_to_str(self, tcx)
206     }
207 }
208
209 pub trait SubstP {
210     fn substp(&self, tcx: &ty::ctxt, param_substs: &param_substs)
211               -> Self;
212 }
213
214 impl<T:Subst+Clone> SubstP for T {
215     fn substp(&self, tcx: &ty::ctxt, substs: &param_substs) -> T {
216         self.subst(tcx, &substs.substs)
217     }
218 }
219
220 // work around bizarre resolve errors
221 pub type RvalueDatum = datum::Datum<datum::Rvalue>;
222 pub type LvalueDatum = datum::Datum<datum::Lvalue>;
223
224 // Function context.  Every LLVM function we create will have one of
225 // these.
226 pub struct FunctionContext<'a> {
227     // The ValueRef returned from a call to llvm::LLVMAddFunction; the
228     // address of the first instruction in the sequence of
229     // instructions for this function that will go in the .text
230     // section of the executable we're generating.
231     pub llfn: ValueRef,
232
233     // The environment argument in a closure.
234     pub llenv: Option<ValueRef>,
235
236     // The place to store the return value. If the return type is immediate,
237     // this is an alloca in the function. Otherwise, it's the hidden first
238     // parameter to the function. After function construction, this should
239     // always be Some.
240     pub llretptr: Cell<Option<ValueRef>>,
241
242     pub entry_bcx: RefCell<Option<&'a Block<'a>>>,
243
244     // These pub elements: "hoisted basic blocks" containing
245     // administrative activities that have to happen in only one place in
246     // the function, due to LLVM's quirks.
247     // A marker for the place where we want to insert the function's static
248     // allocas, so that LLVM will coalesce them into a single alloca call.
249     pub alloca_insert_pt: Cell<Option<ValueRef>>,
250     pub llreturn: Cell<Option<BasicBlockRef>>,
251
252     // The a value alloca'd for calls to upcalls.rust_personality. Used when
253     // outputting the resume instruction.
254     pub personality: Cell<Option<ValueRef>>,
255
256     // True if the caller expects this fn to use the out pointer to
257     // return. Either way, your code should write into llretptr, but if
258     // this value is false, llretptr will be a local alloca.
259     pub caller_expects_out_pointer: bool,
260
261     // Maps arguments to allocas created for them in llallocas.
262     pub llargs: RefCell<NodeMap<LvalueDatum>>,
263
264     // Maps the def_ids for local variables to the allocas created for
265     // them in llallocas.
266     pub lllocals: RefCell<NodeMap<LvalueDatum>>,
267
268     // Same as above, but for closure upvars
269     pub llupvars: RefCell<NodeMap<ValueRef>>,
270
271     // The NodeId of the function, or -1 if it doesn't correspond to
272     // a user-defined function.
273     pub id: ast::NodeId,
274
275     // If this function is being monomorphized, this contains the type
276     // substitutions used.
277     pub param_substs: &'a param_substs,
278
279     // The source span and nesting context where this function comes from, for
280     // error reporting and symbol generation.
281     pub span: Option<Span>,
282
283     // The arena that blocks are allocated from.
284     pub block_arena: &'a TypedArena<Block<'a>>,
285
286     // This function's enclosing crate context.
287     pub ccx: &'a CrateContext,
288
289     // Used and maintained by the debuginfo module.
290     pub debug_context: debuginfo::FunctionDebugContext,
291
292     // Cleanup scopes.
293     pub scopes: RefCell<Vec<cleanup::CleanupScope<'a>> >,
294 }
295
296 impl<'a> FunctionContext<'a> {
297     pub fn arg_pos(&self, arg: uint) -> uint {
298         let arg = self.env_arg_pos() + arg;
299         if self.llenv.is_some() {
300             arg + 1
301         } else {
302             arg
303         }
304     }
305
306     pub fn out_arg_pos(&self) -> uint {
307         assert!(self.caller_expects_out_pointer);
308         0u
309     }
310
311     pub fn env_arg_pos(&self) -> uint {
312         if self.caller_expects_out_pointer {
313             1u
314         } else {
315             0u
316         }
317     }
318
319     pub fn cleanup(&self) {
320         unsafe {
321             llvm::LLVMInstructionEraseFromParent(self.alloca_insert_pt
322                                                      .get()
323                                                      .unwrap());
324         }
325         // Remove the cycle between fcx and bcx, so memory can be freed
326         *self.entry_bcx.borrow_mut() = None;
327     }
328
329     pub fn get_llreturn(&self) -> BasicBlockRef {
330         if self.llreturn.get().is_none() {
331
332             self.llreturn.set(Some(unsafe {
333                 "return".with_c_str(|buf| {
334                     llvm::LLVMAppendBasicBlockInContext(self.ccx.llcx, self.llfn, buf)
335                 })
336             }))
337         }
338
339         self.llreturn.get().unwrap()
340     }
341
342     pub fn new_block(&'a self,
343                      is_lpad: bool,
344                      name: &str,
345                      opt_node_id: Option<ast::NodeId>)
346                      -> &'a Block<'a> {
347         unsafe {
348             let llbb = name.with_c_str(|buf| {
349                     llvm::LLVMAppendBasicBlockInContext(self.ccx.llcx,
350                                                         self.llfn,
351                                                         buf)
352                 });
353             Block::new(llbb, is_lpad, opt_node_id, self)
354         }
355     }
356
357     pub fn new_id_block(&'a self,
358                         name: &str,
359                         node_id: ast::NodeId)
360                         -> &'a Block<'a> {
361         self.new_block(false, name, Some(node_id))
362     }
363
364     pub fn new_temp_block(&'a self,
365                           name: &str)
366                           -> &'a Block<'a> {
367         self.new_block(false, name, None)
368     }
369
370     pub fn join_blocks(&'a self,
371                        id: ast::NodeId,
372                        in_cxs: &[&'a Block<'a>])
373                        -> &'a Block<'a> {
374         let out = self.new_id_block("join", id);
375         let mut reachable = false;
376         for bcx in in_cxs.iter() {
377             if !bcx.unreachable.get() {
378                 build::Br(*bcx, out.llbb);
379                 reachable = true;
380             }
381         }
382         if !reachable {
383             build::Unreachable(out);
384         }
385         return out;
386     }
387 }
388
389 // Basic block context.  We create a block context for each basic block
390 // (single-entry, single-exit sequence of instructions) we generate from Rust
391 // code.  Each basic block we generate is attached to a function, typically
392 // with many basic blocks per function.  All the basic blocks attached to a
393 // function are organized as a directed graph.
394 pub struct Block<'a> {
395     // The BasicBlockRef returned from a call to
396     // llvm::LLVMAppendBasicBlock(llfn, name), which adds a basic
397     // block to the function pointed to by llfn.  We insert
398     // instructions into that block by way of this block context.
399     // The block pointing to this one in the function's digraph.
400     pub llbb: BasicBlockRef,
401     pub terminated: Cell<bool>,
402     pub unreachable: Cell<bool>,
403
404     // Is this block part of a landing pad?
405     pub is_lpad: bool,
406
407     // AST node-id associated with this block, if any. Used for
408     // debugging purposes only.
409     pub opt_node_id: Option<ast::NodeId>,
410
411     // The function context for the function to which this block is
412     // attached.
413     pub fcx: &'a FunctionContext<'a>,
414 }
415
416 impl<'a> Block<'a> {
417     pub fn new<'a>(
418                llbb: BasicBlockRef,
419                is_lpad: bool,
420                opt_node_id: Option<ast::NodeId>,
421                fcx: &'a FunctionContext<'a>)
422                -> &'a Block<'a> {
423         fcx.block_arena.alloc(Block {
424             llbb: llbb,
425             terminated: Cell::new(false),
426             unreachable: Cell::new(false),
427             is_lpad: is_lpad,
428             opt_node_id: opt_node_id,
429             fcx: fcx
430         })
431     }
432
433     pub fn ccx(&self) -> &'a CrateContext { self.fcx.ccx }
434     pub fn tcx(&self) -> &'a ty::ctxt {
435         &self.fcx.ccx.tcx
436     }
437     pub fn sess(&self) -> &'a Session { self.fcx.ccx.sess() }
438
439     pub fn ident(&self, ident: Ident) -> String {
440         token::get_ident(ident).get().to_string()
441     }
442
443     pub fn node_id_to_str(&self, id: ast::NodeId) -> String {
444         self.tcx().map.node_to_str(id).to_string()
445     }
446
447     pub fn expr_to_str(&self, e: &ast::Expr) -> String {
448         e.repr(self.tcx())
449     }
450
451     pub fn def(&self, nid: ast::NodeId) -> def::Def {
452         match self.tcx().def_map.borrow().find(&nid) {
453             Some(&v) => v,
454             None => {
455                 self.tcx().sess.bug(format!(
456                     "no def associated with node id {:?}", nid).as_slice());
457             }
458         }
459     }
460
461     pub fn val_to_str(&self, val: ValueRef) -> String {
462         self.ccx().tn.val_to_str(val)
463     }
464
465     pub fn llty_str(&self, ty: Type) -> String {
466         self.ccx().tn.type_to_str(ty)
467     }
468
469     pub fn ty_to_str(&self, t: ty::t) -> String {
470         t.repr(self.tcx())
471     }
472
473     pub fn to_str(&self) -> String {
474         let blk: *Block = self;
475         format!("[block {}]", blk)
476     }
477 }
478
479 pub struct Result<'a> {
480     pub bcx: &'a Block<'a>,
481     pub val: ValueRef
482 }
483
484 impl<'a> Result<'a> {
485     pub fn new(bcx: &'a Block<'a>, val: ValueRef) -> Result<'a> {
486         Result {
487             bcx: bcx,
488             val: val,
489         }
490     }
491 }
492
493 pub fn val_ty(v: ValueRef) -> Type {
494     unsafe {
495         Type::from_ref(llvm::LLVMTypeOf(v))
496     }
497 }
498
499 // LLVM constant constructors.
500 pub fn C_null(t: Type) -> ValueRef {
501     unsafe {
502         llvm::LLVMConstNull(t.to_ref())
503     }
504 }
505
506 pub fn C_undef(t: Type) -> ValueRef {
507     unsafe {
508         llvm::LLVMGetUndef(t.to_ref())
509     }
510 }
511
512 pub fn C_integral(t: Type, u: u64, sign_extend: bool) -> ValueRef {
513     unsafe {
514         llvm::LLVMConstInt(t.to_ref(), u, sign_extend as Bool)
515     }
516 }
517
518 pub fn C_floating(s: &str, t: Type) -> ValueRef {
519     unsafe {
520         s.with_c_str(|buf| llvm::LLVMConstRealOfString(t.to_ref(), buf))
521     }
522 }
523
524 pub fn C_nil(ccx: &CrateContext) -> ValueRef {
525     C_struct(ccx, [], false)
526 }
527
528 pub fn C_bool(ccx: &CrateContext, val: bool) -> ValueRef {
529     C_integral(Type::bool(ccx), val as u64, false)
530 }
531
532 pub fn C_i1(ccx: &CrateContext, val: bool) -> ValueRef {
533     C_integral(Type::i1(ccx), val as u64, false)
534 }
535
536 pub fn C_i32(ccx: &CrateContext, i: i32) -> ValueRef {
537     C_integral(Type::i32(ccx), i as u64, true)
538 }
539
540 pub fn C_i64(ccx: &CrateContext, i: i64) -> ValueRef {
541     C_integral(Type::i64(ccx), i as u64, true)
542 }
543
544 pub fn C_u64(ccx: &CrateContext, i: u64) -> ValueRef {
545     C_integral(Type::i64(ccx), i, false)
546 }
547
548 pub fn C_int(ccx: &CrateContext, i: int) -> ValueRef {
549     C_integral(ccx.int_type, i as u64, true)
550 }
551
552 pub fn C_uint(ccx: &CrateContext, i: uint) -> ValueRef {
553     C_integral(ccx.int_type, i as u64, false)
554 }
555
556 pub fn C_u8(ccx: &CrateContext, i: uint) -> ValueRef {
557     C_integral(Type::i8(ccx), i as u64, false)
558 }
559
560
561 // This is a 'c-like' raw string, which differs from
562 // our boxed-and-length-annotated strings.
563 pub fn C_cstr(cx: &CrateContext, s: InternedString, null_terminated: bool) -> ValueRef {
564     unsafe {
565         match cx.const_cstr_cache.borrow().find(&s) {
566             Some(&llval) => return llval,
567             None => ()
568         }
569
570         let sc = llvm::LLVMConstStringInContext(cx.llcx,
571                                                 s.get().as_ptr() as *c_char,
572                                                 s.get().len() as c_uint,
573                                                 !null_terminated as Bool);
574
575         let gsym = token::gensym("str");
576         let g = format!("str{}", gsym).with_c_str(|buf| {
577             llvm::LLVMAddGlobal(cx.llmod, val_ty(sc).to_ref(), buf)
578         });
579         llvm::LLVMSetInitializer(g, sc);
580         llvm::LLVMSetGlobalConstant(g, True);
581         lib::llvm::SetLinkage(g, lib::llvm::InternalLinkage);
582
583         cx.const_cstr_cache.borrow_mut().insert(s, g);
584         g
585     }
586 }
587
588 // NB: Do not use `do_spill_noroot` to make this into a constant string, or
589 // you will be kicked off fast isel. See issue #4352 for an example of this.
590 pub fn C_str_slice(cx: &CrateContext, s: InternedString) -> ValueRef {
591     unsafe {
592         let len = s.get().len();
593         let cs = llvm::LLVMConstPointerCast(C_cstr(cx, s, false),
594                                             Type::i8p(cx).to_ref());
595         C_named_struct(cx.tn.find_type("str_slice").unwrap(), [cs, C_uint(cx, len)])
596     }
597 }
598
599 pub fn C_binary_slice(cx: &CrateContext, data: &[u8]) -> ValueRef {
600     unsafe {
601         let len = data.len();
602         let lldata = C_bytes(cx, data);
603
604         let gsym = token::gensym("binary");
605         let g = format!("binary{}", gsym).with_c_str(|buf| {
606             llvm::LLVMAddGlobal(cx.llmod, val_ty(lldata).to_ref(), buf)
607         });
608         llvm::LLVMSetInitializer(g, lldata);
609         llvm::LLVMSetGlobalConstant(g, True);
610         lib::llvm::SetLinkage(g, lib::llvm::InternalLinkage);
611
612         let cs = llvm::LLVMConstPointerCast(g, Type::i8p(cx).to_ref());
613         C_struct(cx, [cs, C_uint(cx, len)], false)
614     }
615 }
616
617 pub fn C_struct(ccx: &CrateContext, elts: &[ValueRef], packed: bool) -> ValueRef {
618     unsafe {
619         llvm::LLVMConstStructInContext(ccx.llcx,
620                                        elts.as_ptr(), elts.len() as c_uint,
621                                        packed as Bool)
622     }
623 }
624
625 pub fn C_named_struct(t: Type, elts: &[ValueRef]) -> ValueRef {
626     unsafe {
627         llvm::LLVMConstNamedStruct(t.to_ref(), elts.as_ptr(), elts.len() as c_uint)
628     }
629 }
630
631 pub fn C_array(ty: Type, elts: &[ValueRef]) -> ValueRef {
632     unsafe {
633         return llvm::LLVMConstArray(ty.to_ref(), elts.as_ptr(), elts.len() as c_uint);
634     }
635 }
636
637 pub fn C_bytes(ccx: &CrateContext, bytes: &[u8]) -> ValueRef {
638     unsafe {
639         let ptr = bytes.as_ptr() as *c_char;
640         return llvm::LLVMConstStringInContext(ccx.llcx, ptr, bytes.len() as c_uint, True);
641     }
642 }
643
644 pub fn get_param(fndecl: ValueRef, param: uint) -> ValueRef {
645     unsafe {
646         llvm::LLVMGetParam(fndecl, param as c_uint)
647     }
648 }
649
650 pub fn const_get_elt(cx: &CrateContext, v: ValueRef, us: &[c_uint])
651                   -> ValueRef {
652     unsafe {
653         let r = llvm::LLVMConstExtractValue(v, us.as_ptr(), us.len() as c_uint);
654
655         debug!("const_get_elt(v={}, us={:?}, r={})",
656                cx.tn.val_to_str(v), us, cx.tn.val_to_str(r));
657
658         return r;
659     }
660 }
661
662 pub fn is_const(v: ValueRef) -> bool {
663     unsafe {
664         llvm::LLVMIsConstant(v) == True
665     }
666 }
667
668 pub fn const_to_int(v: ValueRef) -> c_longlong {
669     unsafe {
670         llvm::LLVMConstIntGetSExtValue(v)
671     }
672 }
673
674 pub fn const_to_uint(v: ValueRef) -> c_ulonglong {
675     unsafe {
676         llvm::LLVMConstIntGetZExtValue(v)
677     }
678 }
679
680 pub fn is_undef(val: ValueRef) -> bool {
681     unsafe {
682         llvm::LLVMIsUndef(val) != False
683     }
684 }
685
686 pub fn is_null(val: ValueRef) -> bool {
687     unsafe {
688         llvm::LLVMIsNull(val) != False
689     }
690 }
691
692 pub fn monomorphize_type(bcx: &Block, t: ty::t) -> ty::t {
693     t.subst(bcx.tcx(), &bcx.fcx.param_substs.substs)
694 }
695
696 pub fn node_id_type(bcx: &Block, id: ast::NodeId) -> ty::t {
697     let tcx = bcx.tcx();
698     let t = ty::node_id_to_type(tcx, id);
699     monomorphize_type(bcx, t)
700 }
701
702 pub fn expr_ty(bcx: &Block, ex: &ast::Expr) -> ty::t {
703     node_id_type(bcx, ex.id)
704 }
705
706 pub fn expr_ty_adjusted(bcx: &Block, ex: &ast::Expr) -> ty::t {
707     monomorphize_type(bcx, ty::expr_ty_adjusted(bcx.tcx(), ex))
708 }
709
710 // Key used to lookup values supplied for type parameters in an expr.
711 #[deriving(PartialEq)]
712 pub enum ExprOrMethodCall {
713     // Type parameters for a path like `None::<int>`
714     ExprId(ast::NodeId),
715
716     // Type parameters for a method call like `a.foo::<int>()`
717     MethodCall(typeck::MethodCall)
718 }
719
720 pub fn node_id_substs(bcx: &Block,
721                       node: ExprOrMethodCall)
722                       -> subst::Substs {
723     let tcx = bcx.tcx();
724
725     let substs = match node {
726         ExprId(id) => {
727             ty::node_id_item_substs(tcx, id).substs
728         }
729         MethodCall(method_call) => {
730             tcx.method_map.borrow().get(&method_call).substs.clone()
731         }
732     };
733
734     if substs.types.any(|t| ty::type_needs_infer(*t)) {
735         bcx.sess().bug(
736             format!("type parameters for node {:?} include inference types: \
737                      {}",
738                     node,
739                     substs.repr(bcx.tcx())).as_slice());
740     }
741
742     substs.substp(tcx, bcx.fcx.param_substs)
743 }
744
745 pub fn node_vtables(bcx: &Block, id: typeck::MethodCall)
746                  -> typeck::vtable_res {
747     bcx.tcx().vtable_map.borrow().find(&id).map(|vts| {
748         resolve_vtables_in_fn_ctxt(bcx.fcx, vts)
749     }).unwrap_or_else(|| subst::VecPerParamSpace::empty())
750 }
751
752 // Apply the typaram substitutions in the FunctionContext to some
753 // vtables. This should eliminate any vtable_params.
754 pub fn resolve_vtables_in_fn_ctxt(fcx: &FunctionContext,
755                                   vts: &typeck::vtable_res)
756                                   -> typeck::vtable_res {
757     resolve_vtables_under_param_substs(fcx.ccx.tcx(),
758                                        fcx.param_substs,
759                                        vts)
760 }
761
762 pub fn resolve_vtables_under_param_substs(tcx: &ty::ctxt,
763                                           param_substs: &param_substs,
764                                           vts: &typeck::vtable_res)
765                                           -> typeck::vtable_res
766 {
767     vts.map(|ds| {
768         resolve_param_vtables_under_param_substs(tcx,
769                                                  param_substs,
770                                                  ds)
771     })
772 }
773
774 pub fn resolve_param_vtables_under_param_substs(tcx: &ty::ctxt,
775                                                 param_substs: &param_substs,
776                                                 ds: &typeck::vtable_param_res)
777                                                 -> typeck::vtable_param_res
778 {
779     ds.iter().map(|d| {
780         resolve_vtable_under_param_substs(tcx,
781                                           param_substs,
782                                           d)
783     }).collect()
784 }
785
786
787
788 pub fn resolve_vtable_under_param_substs(tcx: &ty::ctxt,
789                                          param_substs: &param_substs,
790                                          vt: &typeck::vtable_origin)
791                                          -> typeck::vtable_origin
792 {
793     match *vt {
794         typeck::vtable_static(trait_id, ref vtable_substs, ref sub) => {
795             let vtable_substs = vtable_substs.substp(tcx, param_substs);
796             typeck::vtable_static(
797                 trait_id,
798                 vtable_substs,
799                 resolve_vtables_under_param_substs(tcx, param_substs, sub))
800         }
801         typeck::vtable_param(n_param, n_bound) => {
802             find_vtable(tcx, param_substs, n_param, n_bound)
803         }
804         typeck::vtable_error => typeck::vtable_error
805     }
806 }
807
808 pub fn find_vtable(tcx: &ty::ctxt,
809                    ps: &param_substs,
810                    n_param: typeck::param_index,
811                    n_bound: uint)
812                    -> typeck::vtable_origin {
813     debug!("find_vtable(n_param={:?}, n_bound={}, ps={})",
814            n_param, n_bound, ps.repr(tcx));
815
816     let param_bounds = ps.vtables.get(n_param.space,
817                                       n_param.index);
818     param_bounds.get(n_bound).clone()
819 }
820
821 pub fn langcall(bcx: &Block,
822                 span: Option<Span>,
823                 msg: &str,
824                 li: LangItem)
825                 -> ast::DefId {
826     match bcx.tcx().lang_items.require(li) {
827         Ok(id) => id,
828         Err(s) => {
829             let msg = format!("{} {}", msg, s);
830             match span {
831                 Some(span) => bcx.tcx().sess.span_fatal(span, msg.as_slice()),
832                 None => bcx.tcx().sess.fatal(msg.as_slice()),
833             }
834         }
835     }
836 }