]> git.lizzy.rs Git - rust.git/blob - src/librustc/middle/trans/common.rs
auto merge of #13015 : tbu-/rust/pr_remove_immut, r=alexcrichton
[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::substs;
28 use middle::ty;
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 std::c_str::ToCStr;
36 use std::cell::{Cell, RefCell};
37 use std::libc::{c_uint, c_longlong, c_ulonglong, c_char};
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)))
112 }
113
114 pub struct tydesc_info {
115     ty: ty::t,
116     tydesc: ValueRef,
117     size: ValueRef,
118     align: ValueRef,
119     name: ValueRef,
120     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     id: ast::NodeId,
151     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 Stats {
159     n_static_tydescs: Cell<uint>,
160     n_glues_created: Cell<uint>,
161     n_null_glues: Cell<uint>,
162     n_real_glues: Cell<uint>,
163     n_fns: Cell<uint>,
164     n_monos: Cell<uint>,
165     n_inlines: Cell<uint>,
166     n_closures: Cell<uint>,
167     n_llvm_insns: Cell<uint>,
168     llvm_insns: RefCell<HashMap<~str, uint>>,
169     // (ident, time-in-ms, llvm-instructions)
170     fn_stats: RefCell<Vec<(~str, uint, uint)> >,
171 }
172
173 pub struct BuilderRef_res {
174     b: BuilderRef,
175 }
176
177 impl Drop for BuilderRef_res {
178     fn drop(&mut self) {
179         unsafe {
180             llvm::LLVMDisposeBuilder(self.b);
181         }
182     }
183 }
184
185 pub fn BuilderRef_res(b: BuilderRef) -> BuilderRef_res {
186     BuilderRef_res {
187         b: b
188     }
189 }
190
191 pub type ExternMap = HashMap<~str, ValueRef>;
192
193 // Here `self_ty` is the real type of the self parameter to this method. It
194 // will only be set in the case of default methods.
195 pub struct param_substs {
196     tys: Vec<ty::t> ,
197     self_ty: Option<ty::t>,
198     vtables: Option<typeck::vtable_res>,
199     self_vtables: Option<typeck::vtable_param_res>
200 }
201
202 impl param_substs {
203     pub fn validate(&self) {
204         for t in self.tys.iter() { assert!(!ty::type_needs_infer(*t)); }
205         for t in self.self_ty.iter() { assert!(!ty::type_needs_infer(*t)); }
206     }
207 }
208
209 fn param_substs_to_str(this: &param_substs, tcx: &ty::ctxt) -> ~str {
210     format!("param_substs \\{tys:{}, vtables:{}\\}",
211          this.tys.repr(tcx),
212          this.vtables.repr(tcx))
213 }
214
215 impl Repr for param_substs {
216     fn repr(&self, tcx: &ty::ctxt) -> ~str {
217         param_substs_to_str(self, tcx)
218     }
219 }
220
221 // work around bizarre resolve errors
222 pub type RvalueDatum = datum::Datum<datum::Rvalue>;
223 pub type LvalueDatum = datum::Datum<datum::Lvalue>;
224
225 // Function context.  Every LLVM function we create will have one of
226 // these.
227 pub struct FunctionContext<'a> {
228     // The ValueRef returned from a call to llvm::LLVMAddFunction; the
229     // address of the first instruction in the sequence of
230     // instructions for this function that will go in the .text
231     // section of the executable we're generating.
232     llfn: ValueRef,
233
234     // The environment argument in a closure.
235     llenv: Option<ValueRef>,
236
237     // The place to store the return value. If the return type is immediate,
238     // this is an alloca in the function. Otherwise, it's the hidden first
239     // parameter to the function. After function construction, this should
240     // always be Some.
241     llretptr: Cell<Option<ValueRef>>,
242
243     entry_bcx: RefCell<Option<&'a Block<'a>>>,
244
245     // These elements: "hoisted basic blocks" containing
246     // administrative activities that have to happen in only one place in
247     // the function, due to LLVM's quirks.
248     // A marker for the place where we want to insert the function's static
249     // allocas, so that LLVM will coalesce them into a single alloca call.
250     alloca_insert_pt: Cell<Option<ValueRef>>,
251     llreturn: Cell<Option<BasicBlockRef>>,
252
253     // The a value alloca'd for calls to upcalls.rust_personality. Used when
254     // outputting the resume instruction.
255     personality: Cell<Option<ValueRef>>,
256
257     // True if the caller expects this fn to use the out pointer to
258     // return. Either way, your code should write into llretptr, but if
259     // this value is false, llretptr will be a local alloca.
260     caller_expects_out_pointer: bool,
261
262     // Maps arguments to allocas created for them in llallocas.
263     llargs: RefCell<NodeMap<LvalueDatum>>,
264
265     // Maps the def_ids for local variables to the allocas created for
266     // them in llallocas.
267     lllocals: RefCell<NodeMap<LvalueDatum>>,
268
269     // Same as above, but for closure upvars
270     llupvars: RefCell<NodeMap<ValueRef>>,
271
272     // The NodeId of the function, or -1 if it doesn't correspond to
273     // a user-defined function.
274     id: ast::NodeId,
275
276     // If this function is being monomorphized, this contains the type
277     // substitutions used.
278     param_substs: Option<@param_substs>,
279
280     // The source span and nesting context where this function comes from, for
281     // error reporting and symbol generation.
282     span: Option<Span>,
283
284     // The arena that blocks are allocated from.
285     block_arena: &'a TypedArena<Block<'a>>,
286
287     // This function's enclosing crate context.
288     ccx: &'a CrateContext,
289
290     // Used and maintained by the debuginfo module.
291     debug_context: debuginfo::FunctionDebugContext,
292
293     // Cleanup scopes.
294     scopes: RefCell<Vec<cleanup::CleanupScope<'a>> >,
295 }
296
297 impl<'a> FunctionContext<'a> {
298     pub fn arg_pos(&self, arg: uint) -> uint {
299         let arg = self.env_arg_pos() + arg;
300         if self.llenv.is_some() {
301             arg + 1
302         } else {
303             arg
304         }
305     }
306
307     pub fn out_arg_pos(&self) -> uint {
308         assert!(self.caller_expects_out_pointer);
309         0u
310     }
311
312     pub fn env_arg_pos(&self) -> uint {
313         if self.caller_expects_out_pointer {
314             1u
315         } else {
316             0u
317         }
318     }
319
320     pub fn cleanup(&self) {
321         unsafe {
322             llvm::LLVMInstructionEraseFromParent(self.alloca_insert_pt
323                                                      .get()
324                                                      .unwrap());
325         }
326         // Remove the cycle between fcx and bcx, so memory can be freed
327         self.entry_bcx.set(None);
328     }
329
330     pub fn get_llreturn(&self) -> BasicBlockRef {
331         if self.llreturn.get().is_none() {
332
333             self.llreturn.set(Some(unsafe {
334                 "return".with_c_str(|buf| {
335                     llvm::LLVMAppendBasicBlockInContext(self.ccx.llcx, self.llfn, buf)
336                 })
337             }))
338         }
339
340         self.llreturn.get().unwrap()
341     }
342
343     pub fn new_block(&'a self,
344                      is_lpad: bool,
345                      name: &str,
346                      opt_node_id: Option<ast::NodeId>)
347                      -> &'a Block<'a> {
348         unsafe {
349             let llbb = name.with_c_str(|buf| {
350                     llvm::LLVMAppendBasicBlockInContext(self.ccx.llcx,
351                                                         self.llfn,
352                                                         buf)
353                 });
354             Block::new(llbb, is_lpad, opt_node_id, self)
355         }
356     }
357
358     pub fn new_id_block(&'a self,
359                         name: &str,
360                         node_id: ast::NodeId)
361                         -> &'a Block<'a> {
362         self.new_block(false, name, Some(node_id))
363     }
364
365     pub fn new_temp_block(&'a self,
366                           name: &str)
367                           -> &'a Block<'a> {
368         self.new_block(false, name, None)
369     }
370
371     pub fn join_blocks(&'a self,
372                        id: ast::NodeId,
373                        in_cxs: &[&'a Block<'a>])
374                        -> &'a Block<'a> {
375         let out = self.new_id_block("join", id);
376         let mut reachable = false;
377         for bcx in in_cxs.iter() {
378             if !bcx.unreachable.get() {
379                 build::Br(*bcx, out.llbb);
380                 reachable = true;
381             }
382         }
383         if !reachable {
384             build::Unreachable(out);
385         }
386         return out;
387     }
388 }
389
390 // Heap selectors. Indicate which heap something should go on.
391 #[deriving(Eq)]
392 pub enum heap {
393     heap_managed,
394     heap_exchange,
395     heap_exchange_closure
396 }
397
398 // Basic block context.  We create a block context for each basic block
399 // (single-entry, single-exit sequence of instructions) we generate from Rust
400 // code.  Each basic block we generate is attached to a function, typically
401 // with many basic blocks per function.  All the basic blocks attached to a
402 // function are organized as a directed graph.
403 pub struct Block<'a> {
404     // The BasicBlockRef returned from a call to
405     // llvm::LLVMAppendBasicBlock(llfn, name), which adds a basic
406     // block to the function pointed to by llfn.  We insert
407     // instructions into that block by way of this block context.
408     // The block pointing to this one in the function's digraph.
409     llbb: BasicBlockRef,
410     terminated: Cell<bool>,
411     unreachable: Cell<bool>,
412
413     // Is this block part of a landing pad?
414     is_lpad: bool,
415
416     // AST node-id associated with this block, if any. Used for
417     // debugging purposes only.
418     opt_node_id: Option<ast::NodeId>,
419
420     // The function context for the function to which this block is
421     // attached.
422     fcx: &'a FunctionContext<'a>,
423 }
424
425 impl<'a> Block<'a> {
426     pub fn new<'a>(
427                llbb: BasicBlockRef,
428                is_lpad: bool,
429                opt_node_id: Option<ast::NodeId>,
430                fcx: &'a FunctionContext<'a>)
431                -> &'a Block<'a> {
432         fcx.block_arena.alloc(Block {
433             llbb: llbb,
434             terminated: Cell::new(false),
435             unreachable: Cell::new(false),
436             is_lpad: is_lpad,
437             opt_node_id: opt_node_id,
438             fcx: fcx
439         })
440     }
441
442     pub fn ccx(&self) -> &'a CrateContext { self.fcx.ccx }
443     pub fn tcx(&self) -> &'a ty::ctxt {
444         &self.fcx.ccx.tcx
445     }
446     pub fn sess(&self) -> &'a Session { self.fcx.ccx.sess() }
447
448     pub fn ident(&self, ident: Ident) -> ~str {
449         token::get_ident(ident).get().to_str()
450     }
451
452     pub fn node_id_to_str(&self, id: ast::NodeId) -> ~str {
453         self.tcx().map.node_to_str(id)
454     }
455
456     pub fn expr_to_str(&self, e: &ast::Expr) -> ~str {
457         e.repr(self.tcx())
458     }
459
460     pub fn expr_is_lval(&self, e: &ast::Expr) -> bool {
461         ty::expr_is_lval(self.tcx(), self.ccx().maps.method_map, e)
462     }
463
464     pub fn expr_kind(&self, e: &ast::Expr) -> ty::ExprKind {
465         ty::expr_kind(self.tcx(), self.ccx().maps.method_map, e)
466     }
467
468     pub fn def(&self, nid: ast::NodeId) -> ast::Def {
469         let def_map = self.tcx().def_map.borrow();
470         match def_map.get().find(&nid) {
471             Some(&v) => v,
472             None => {
473                 self.tcx().sess.bug(format!(
474                     "no def associated with node id {:?}", nid));
475             }
476         }
477     }
478
479     pub fn val_to_str(&self, val: ValueRef) -> ~str {
480         self.ccx().tn.val_to_str(val)
481     }
482
483     pub fn llty_str(&self, ty: Type) -> ~str {
484         self.ccx().tn.type_to_str(ty)
485     }
486
487     pub fn ty_to_str(&self, t: ty::t) -> ~str {
488         t.repr(self.tcx())
489     }
490
491     pub fn to_str(&self) -> ~str {
492         let blk: *Block = self;
493         format!("[block {}]", blk)
494     }
495 }
496
497 pub struct Result<'a> {
498     bcx: &'a Block<'a>,
499     val: ValueRef
500 }
501
502 pub fn rslt<'a>(bcx: &'a Block<'a>, val: ValueRef) -> Result<'a> {
503     Result {
504         bcx: bcx,
505         val: val,
506     }
507 }
508
509 impl<'a> Result<'a> {
510     pub fn unpack(&self, bcx: &mut &'a Block<'a>) -> ValueRef {
511         *bcx = self.bcx;
512         return self.val;
513     }
514 }
515
516 pub fn val_ty(v: ValueRef) -> Type {
517     unsafe {
518         Type::from_ref(llvm::LLVMTypeOf(v))
519     }
520 }
521
522 // LLVM constant constructors.
523 pub fn C_null(t: Type) -> ValueRef {
524     unsafe {
525         llvm::LLVMConstNull(t.to_ref())
526     }
527 }
528
529 pub fn C_undef(t: Type) -> ValueRef {
530     unsafe {
531         llvm::LLVMGetUndef(t.to_ref())
532     }
533 }
534
535 pub fn C_integral(t: Type, u: u64, sign_extend: bool) -> ValueRef {
536     unsafe {
537         llvm::LLVMConstInt(t.to_ref(), u, sign_extend as Bool)
538     }
539 }
540
541 pub fn C_floating(s: &str, t: Type) -> ValueRef {
542     unsafe {
543         s.with_c_str(|buf| llvm::LLVMConstRealOfString(t.to_ref(), buf))
544     }
545 }
546
547 pub fn C_nil(ccx: &CrateContext) -> ValueRef {
548     C_struct(ccx, [], false)
549 }
550
551 pub fn C_bool(ccx: &CrateContext, val: bool) -> ValueRef {
552     C_integral(Type::bool(ccx), val as u64, false)
553 }
554
555 pub fn C_i1(ccx: &CrateContext, val: bool) -> ValueRef {
556     C_integral(Type::i1(ccx), val as u64, false)
557 }
558
559 pub fn C_i32(ccx: &CrateContext, i: i32) -> ValueRef {
560     C_integral(Type::i32(ccx), i as u64, true)
561 }
562
563 pub fn C_i64(ccx: &CrateContext, i: i64) -> ValueRef {
564     C_integral(Type::i64(ccx), i as u64, true)
565 }
566
567 pub fn C_u64(ccx: &CrateContext, i: u64) -> ValueRef {
568     C_integral(Type::i64(ccx), i, false)
569 }
570
571 pub fn C_int(ccx: &CrateContext, i: int) -> ValueRef {
572     C_integral(ccx.int_type, i as u64, true)
573 }
574
575 pub fn C_uint(ccx: &CrateContext, i: uint) -> ValueRef {
576     C_integral(ccx.int_type, i as u64, false)
577 }
578
579 pub fn C_u8(ccx: &CrateContext, i: uint) -> ValueRef {
580     C_integral(Type::i8(ccx), i as u64, false)
581 }
582
583
584 // This is a 'c-like' raw string, which differs from
585 // our boxed-and-length-annotated strings.
586 pub fn C_cstr(cx: &CrateContext, s: InternedString) -> ValueRef {
587     unsafe {
588         {
589             let const_cstr_cache = cx.const_cstr_cache.borrow();
590             match const_cstr_cache.get().find(&s) {
591                 Some(&llval) => return llval,
592                 None => ()
593             }
594         }
595
596         let sc = llvm::LLVMConstStringInContext(cx.llcx,
597                                                 s.get().as_ptr() as *c_char,
598                                                 s.get().len() as c_uint,
599                                                 False);
600
601         let gsym = token::gensym("str");
602         let g = format!("str{}", gsym).with_c_str(|buf| {
603             llvm::LLVMAddGlobal(cx.llmod, val_ty(sc).to_ref(), buf)
604         });
605         llvm::LLVMSetInitializer(g, sc);
606         llvm::LLVMSetGlobalConstant(g, True);
607         lib::llvm::SetLinkage(g, lib::llvm::InternalLinkage);
608
609         let mut const_cstr_cache = cx.const_cstr_cache.borrow_mut();
610         const_cstr_cache.get().insert(s, g);
611         g
612     }
613 }
614
615 // NB: Do not use `do_spill_noroot` to make this into a constant string, or
616 // you will be kicked off fast isel. See issue #4352 for an example of this.
617 pub fn C_str_slice(cx: &CrateContext, s: InternedString) -> ValueRef {
618     unsafe {
619         let len = s.get().len();
620         let cs = llvm::LLVMConstPointerCast(C_cstr(cx, s), Type::i8p(cx).to_ref());
621         C_struct(cx, [cs, C_uint(cx, len)], false)
622     }
623 }
624
625 pub fn C_binary_slice(cx: &CrateContext, data: &[u8]) -> ValueRef {
626     unsafe {
627         let len = data.len();
628         let lldata = C_bytes(cx, data);
629
630         let gsym = token::gensym("binary");
631         let g = format!("binary{}", gsym).with_c_str(|buf| {
632             llvm::LLVMAddGlobal(cx.llmod, val_ty(lldata).to_ref(), buf)
633         });
634         llvm::LLVMSetInitializer(g, lldata);
635         llvm::LLVMSetGlobalConstant(g, True);
636         lib::llvm::SetLinkage(g, lib::llvm::InternalLinkage);
637
638         let cs = llvm::LLVMConstPointerCast(g, Type::i8p(cx).to_ref());
639         C_struct(cx, [cs, C_uint(cx, len)], false)
640     }
641 }
642
643 pub fn C_struct(ccx: &CrateContext, elts: &[ValueRef], packed: bool) -> ValueRef {
644     unsafe {
645         llvm::LLVMConstStructInContext(ccx.llcx,
646                                        elts.as_ptr(), elts.len() as c_uint,
647                                        packed as Bool)
648     }
649 }
650
651 pub fn C_named_struct(t: Type, elts: &[ValueRef]) -> ValueRef {
652     unsafe {
653         llvm::LLVMConstNamedStruct(t.to_ref(), elts.as_ptr(), elts.len() as c_uint)
654     }
655 }
656
657 pub fn C_array(ty: Type, elts: &[ValueRef]) -> ValueRef {
658     unsafe {
659         return llvm::LLVMConstArray(ty.to_ref(), elts.as_ptr(), elts.len() as c_uint);
660     }
661 }
662
663 pub fn C_bytes(ccx: &CrateContext, bytes: &[u8]) -> ValueRef {
664     unsafe {
665         let ptr = bytes.as_ptr() as *c_char;
666         return llvm::LLVMConstStringInContext(ccx.llcx, ptr, bytes.len() as c_uint, True);
667     }
668 }
669
670 pub fn get_param(fndecl: ValueRef, param: uint) -> ValueRef {
671     unsafe {
672         llvm::LLVMGetParam(fndecl, param as c_uint)
673     }
674 }
675
676 pub fn const_get_elt(cx: &CrateContext, v: ValueRef, us: &[c_uint])
677                   -> ValueRef {
678     unsafe {
679         let r = llvm::LLVMConstExtractValue(v, us.as_ptr(), us.len() as c_uint);
680
681         debug!("const_get_elt(v={}, us={:?}, r={})",
682                cx.tn.val_to_str(v), us, cx.tn.val_to_str(r));
683
684         return r;
685     }
686 }
687
688 pub fn is_const(v: ValueRef) -> bool {
689     unsafe {
690         llvm::LLVMIsConstant(v) == True
691     }
692 }
693
694 pub fn const_to_int(v: ValueRef) -> c_longlong {
695     unsafe {
696         llvm::LLVMConstIntGetSExtValue(v)
697     }
698 }
699
700 pub fn const_to_uint(v: ValueRef) -> c_ulonglong {
701     unsafe {
702         llvm::LLVMConstIntGetZExtValue(v)
703     }
704 }
705
706 pub fn is_undef(val: ValueRef) -> bool {
707     unsafe {
708         llvm::LLVMIsUndef(val) != False
709     }
710 }
711
712 pub fn is_null(val: ValueRef) -> bool {
713     unsafe {
714         llvm::LLVMIsNull(val) != False
715     }
716 }
717
718 // Used to identify cached monomorphized functions and vtables
719 #[deriving(Eq, Hash)]
720 pub enum mono_param_id {
721     mono_precise(ty::t, Option<@Vec<mono_id> >),
722     mono_any,
723     mono_repr(uint /* size */,
724               uint /* align */,
725               MonoDataClass,
726               datum::RvalueMode),
727 }
728
729 #[deriving(Eq, Hash)]
730 pub enum MonoDataClass {
731     MonoBits,    // Anything not treated differently from arbitrary integer data
732     MonoNonNull, // Non-null pointers (used for optional-pointer optimization)
733     // FIXME(#3547)---scalars and floats are
734     // treated differently in most ABIs.  But we
735     // should be doing something more detailed
736     // here.
737     MonoFloat
738 }
739
740 pub fn mono_data_classify(t: ty::t) -> MonoDataClass {
741     match ty::get(t).sty {
742         ty::ty_float(_) => MonoFloat,
743         ty::ty_rptr(..) | ty::ty_uniq(..) | ty::ty_box(..) |
744         ty::ty_str(ty::vstore_uniq) | ty::ty_vec(_, ty::vstore_uniq) |
745         ty::ty_bare_fn(..) => MonoNonNull,
746         // Is that everything?  Would closures or slices qualify?
747         _ => MonoBits
748     }
749 }
750
751 #[deriving(Eq, Hash)]
752 pub struct mono_id_ {
753     def: ast::DefId,
754     params: Vec<mono_param_id> }
755
756 pub type mono_id = @mono_id_;
757
758 pub fn umax(cx: &Block, a: ValueRef, b: ValueRef) -> ValueRef {
759     let cond = build::ICmp(cx, lib::llvm::IntULT, a, b);
760     return build::Select(cx, cond, b, a);
761 }
762
763 pub fn umin(cx: &Block, a: ValueRef, b: ValueRef) -> ValueRef {
764     let cond = build::ICmp(cx, lib::llvm::IntULT, a, b);
765     return build::Select(cx, cond, a, b);
766 }
767
768 pub fn align_to(cx: &Block, off: ValueRef, align: ValueRef) -> ValueRef {
769     let mask = build::Sub(cx, align, C_int(cx.ccx(), 1));
770     let bumped = build::Add(cx, off, mask);
771     return build::And(cx, bumped, build::Not(cx, mask));
772 }
773
774 pub fn monomorphize_type(bcx: &Block, t: ty::t) -> ty::t {
775     match bcx.fcx.param_substs {
776         Some(substs) => {
777             ty::subst_tps(bcx.tcx(), substs.tys.as_slice(), substs.self_ty, t)
778         }
779         _ => {
780             assert!(!ty::type_has_params(t));
781             assert!(!ty::type_has_self(t));
782             t
783         }
784     }
785 }
786
787 pub fn node_id_type(bcx: &Block, id: ast::NodeId) -> ty::t {
788     let tcx = bcx.tcx();
789     let t = ty::node_id_to_type(tcx, id);
790     monomorphize_type(bcx, t)
791 }
792
793 pub fn expr_ty(bcx: &Block, ex: &ast::Expr) -> ty::t {
794     node_id_type(bcx, ex.id)
795 }
796
797 pub fn expr_ty_adjusted(bcx: &Block, ex: &ast::Expr) -> ty::t {
798     let tcx = bcx.tcx();
799     let t = ty::expr_ty_adjusted(tcx, ex, bcx.ccx().maps.method_map.borrow().get());
800     monomorphize_type(bcx, t)
801 }
802
803 // Key used to lookup values supplied for type parameters in an expr.
804 #[deriving(Eq)]
805 pub enum ExprOrMethodCall {
806     // Type parameters for a path like `None::<int>`
807     ExprId(ast::NodeId),
808
809     // Type parameters for a method call like `a.foo::<int>()`
810     MethodCall(typeck::MethodCall)
811 }
812
813 pub fn node_id_type_params(bcx: &Block, node: ExprOrMethodCall) -> Vec<ty::t> {
814     let tcx = bcx.tcx();
815     let params = match node {
816         ExprId(id) => ty::node_id_to_type_params(tcx, id),
817         MethodCall(method_call) => {
818             bcx.ccx().maps.method_map.borrow().get().get(&method_call).substs.tps.clone()
819         }
820     };
821
822     if !params.iter().all(|t| !ty::type_needs_infer(*t)) {
823         bcx.sess().bug(
824             format!("type parameters for node {:?} include inference types: {}",
825                  node, params.map(|t| bcx.ty_to_str(*t)).connect(",")));
826     }
827
828     match bcx.fcx.param_substs {
829       Some(substs) => {
830         params.iter().map(|t| {
831             ty::subst_tps(tcx, substs.tys.as_slice(), substs.self_ty, *t)
832         }).collect()
833       }
834       _ => params
835     }
836 }
837
838 pub fn node_vtables(bcx: &Block, id: ast::NodeId)
839                  -> Option<typeck::vtable_res> {
840     let vtable_map = bcx.ccx().maps.vtable_map.borrow();
841     let raw_vtables = vtable_map.get().find(&id);
842     raw_vtables.map(|vts| resolve_vtables_in_fn_ctxt(bcx.fcx, *vts))
843 }
844
845 // Apply the typaram substitutions in the FunctionContext to some
846 // vtables. This should eliminate any vtable_params.
847 pub fn resolve_vtables_in_fn_ctxt(fcx: &FunctionContext, vts: typeck::vtable_res)
848     -> typeck::vtable_res {
849     resolve_vtables_under_param_substs(fcx.ccx.tcx(),
850                                        fcx.param_substs,
851                                        vts)
852 }
853
854 pub fn resolve_vtables_under_param_substs(tcx: &ty::ctxt,
855                                           param_substs: Option<@param_substs>,
856                                           vts: typeck::vtable_res)
857     -> typeck::vtable_res {
858     @vts.iter().map(|ds|
859       resolve_param_vtables_under_param_substs(tcx,
860                                                param_substs,
861                                                *ds))
862         .collect()
863 }
864
865 pub fn resolve_param_vtables_under_param_substs(
866     tcx: &ty::ctxt,
867     param_substs: Option<@param_substs>,
868     ds: typeck::vtable_param_res)
869     -> typeck::vtable_param_res {
870     @ds.iter().map(
871         |d| resolve_vtable_under_param_substs(tcx,
872                                               param_substs,
873                                               d))
874         .collect()
875 }
876
877
878
879 pub fn resolve_vtable_under_param_substs(tcx: &ty::ctxt,
880                                          param_substs: Option<@param_substs>,
881                                          vt: &typeck::vtable_origin)
882                                          -> typeck::vtable_origin {
883     match *vt {
884         typeck::vtable_static(trait_id, ref tys, sub) => {
885             let tys = match param_substs {
886                 Some(substs) => {
887                     tys.iter().map(|t| {
888                         ty::subst_tps(tcx,
889                                       substs.tys.as_slice(),
890                                       substs.self_ty,
891                                       *t)
892                     }).collect()
893                 }
894                 _ => Vec::from_slice(tys.as_slice())
895             };
896             typeck::vtable_static(
897                 trait_id, tys,
898                 resolve_vtables_under_param_substs(tcx, param_substs, sub))
899         }
900         typeck::vtable_param(n_param, n_bound) => {
901             match param_substs {
902                 Some(substs) => {
903                     find_vtable(tcx, substs, n_param, n_bound)
904                 }
905                 _ => {
906                     tcx.sess.bug(format!(
907                         "resolve_vtable_under_param_substs: asked to lookup \
908                          but no vtables in the fn_ctxt!"))
909                 }
910             }
911         }
912     }
913 }
914
915 pub fn find_vtable(tcx: &ty::ctxt,
916                    ps: &param_substs,
917                    n_param: typeck::param_index,
918                    n_bound: uint)
919                    -> typeck::vtable_origin {
920     debug!("find_vtable(n_param={:?}, n_bound={}, ps={})",
921            n_param, n_bound, ps.repr(tcx));
922
923     let param_bounds = match n_param {
924         typeck::param_self => ps.self_vtables.expect("self vtables missing"),
925         typeck::param_numbered(n) => {
926             let tables = ps.vtables
927                 .expect("vtables missing where they are needed");
928             *tables.get(n)
929         }
930     };
931     param_bounds.get(n_bound).clone()
932 }
933
934 pub fn dummy_substs(tps: Vec<ty::t> ) -> ty::substs {
935     substs {
936         regions: ty::ErasedRegions,
937         self_ty: None,
938         tps: tps
939     }
940 }
941
942 pub fn filename_and_line_num_from_span(bcx: &Block, span: Span)
943                                        -> (ValueRef, ValueRef) {
944     let loc = bcx.sess().codemap().lookup_char_pos(span.lo);
945     let filename_cstr = C_cstr(bcx.ccx(),
946                                token::intern_and_get_ident(loc.file.deref().name));
947     let filename = build::PointerCast(bcx, filename_cstr, Type::i8p(bcx.ccx()));
948     let line = C_int(bcx.ccx(), loc.line as int);
949     (filename, line)
950 }
951
952 // Casts a Rust bool value to an i1.
953 pub fn bool_to_i1(bcx: &Block, llval: ValueRef) -> ValueRef {
954     build::ICmp(bcx, lib::llvm::IntNE, llval, C_bool(bcx.ccx(), false))
955 }
956
957 pub fn langcall(bcx: &Block,
958                 span: Option<Span>,
959                 msg: &str,
960                 li: LangItem)
961                 -> ast::DefId {
962     match bcx.tcx().lang_items.require(li) {
963         Ok(id) => id,
964         Err(s) => {
965             let msg = format!("{} {}", msg, s);
966             match span {
967                 Some(span) => { bcx.tcx().sess.span_fatal(span, msg); }
968                 None => { bcx.tcx().sess.fatal(msg); }
969             }
970         }
971     }
972 }