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