]> git.lizzy.rs Git - rust.git/blob - src/librustc_trans/trans/common.rs
auto merge of #19640 : aliblong/rust/power_of_two_reform, r=Gankro
[rust.git] / src / librustc_trans / 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)]
12
13 //! Code that is useful in various trans modules.
14
15 pub use self::ExprOrMethodCall::*;
16
17 use session::Session;
18 use llvm;
19 use llvm::{ValueRef, BasicBlockRef, BuilderRef, ContextRef};
20 use llvm::{True, False, Bool};
21 use middle::def;
22 use middle::infer;
23 use middle::lang_items::LangItem;
24 use middle::mem_categorization as mc;
25 use middle::region;
26 use middle::subst;
27 use middle::subst::{Subst, Substs};
28 use trans::base;
29 use trans::build;
30 use trans::cleanup;
31 use trans::datum;
32 use trans::debuginfo;
33 use trans::machine;
34 use trans::type_::Type;
35 use trans::type_of;
36 use middle::traits;
37 use middle::ty::{mod, Ty};
38 use middle::ty_fold;
39 use middle::ty_fold::TypeFoldable;
40 use util::ppaux::Repr;
41 use util::nodemap::{DefIdMap, FnvHashMap, NodeMap};
42
43 use arena::TypedArena;
44 use libc::{c_uint, c_char};
45 use std::c_str::ToCStr;
46 use std::cell::{Cell, RefCell};
47 use std::rc::Rc;
48 use std::vec::Vec;
49 use syntax::ast::Ident;
50 use syntax::ast;
51 use syntax::ast_map::{PathElem, PathName};
52 use syntax::codemap::Span;
53 use syntax::parse::token::InternedString;
54 use syntax::parse::token;
55
56 pub use trans::context::CrateContext;
57
58 fn type_is_newtype_immediate<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
59                                        ty: Ty<'tcx>) -> bool {
60     match ty.sty {
61         ty::ty_struct(def_id, ref substs) => {
62             let fields = ty::struct_fields(ccx.tcx(), def_id, substs);
63             fields.len() == 1 &&
64                 fields[0].name ==
65                     token::special_idents::unnamed_field.name &&
66                 type_is_immediate(ccx, fields[0].mt.ty)
67         }
68         _ => false
69     }
70 }
71
72 pub fn type_is_immediate<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool {
73     use trans::machine::llsize_of_alloc;
74     use trans::type_of::sizing_type_of;
75
76     let tcx = ccx.tcx();
77     let simple = ty::type_is_scalar(ty) ||
78         ty::type_is_unique(ty) || ty::type_is_region_ptr(ty) ||
79         type_is_newtype_immediate(ccx, ty) ||
80         ty::type_is_simd(tcx, ty);
81     if simple && !ty::type_is_fat_ptr(tcx, ty) {
82         return true;
83     }
84     if !ty::type_is_sized(tcx, ty) {
85         return false;
86     }
87     match ty.sty {
88         ty::ty_struct(..) | ty::ty_enum(..) | ty::ty_tup(..) |
89         ty::ty_unboxed_closure(..) => {
90             let llty = sizing_type_of(ccx, ty);
91             llsize_of_alloc(ccx, llty) <= llsize_of_alloc(ccx, ccx.int_type())
92         }
93         _ => type_is_zero_size(ccx, ty)
94     }
95 }
96
97 /// Identify types which have size zero at runtime.
98 pub fn type_is_zero_size<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool {
99     use trans::machine::llsize_of_alloc;
100     use trans::type_of::sizing_type_of;
101     let llty = sizing_type_of(ccx, ty);
102     llsize_of_alloc(ccx, llty) == 0
103 }
104
105 /// Identifies types which we declare to be equivalent to `void` in C for the purpose of function
106 /// return types. These are `()`, bot, and uninhabited enums. Note that all such types are also
107 /// zero-size, but not all zero-size types use a `void` return type (in order to aid with C ABI
108 /// compatibility).
109 pub fn return_type_is_void(ccx: &CrateContext, ty: Ty) -> bool {
110     ty::type_is_nil(ty) || ty::type_is_empty(ccx.tcx(), ty)
111 }
112
113 /// Generates a unique symbol based off the name given. This is used to create
114 /// unique symbols for things like closures.
115 pub fn gensym_name(name: &str) -> PathElem {
116     let num = token::gensym(name).uint();
117     // use one colon which will get translated to a period by the mangler, and
118     // we're guaranteed that `num` is globally unique for this crate.
119     PathName(token::gensym(format!("{}:{}", name, num).as_slice()))
120 }
121
122 #[deriving(Copy)]
123 pub struct tydesc_info<'tcx> {
124     pub ty: Ty<'tcx>,
125     pub tydesc: ValueRef,
126     pub size: ValueRef,
127     pub align: ValueRef,
128     pub name: ValueRef,
129 }
130
131 /*
132  * A note on nomenclature of linking: "extern", "foreign", and "upcall".
133  *
134  * An "extern" is an LLVM symbol we wind up emitting an undefined external
135  * reference to. This means "we don't have the thing in this compilation unit,
136  * please make sure you link it in at runtime". This could be a reference to
137  * C code found in a C library, or rust code found in a rust crate.
138  *
139  * Most "externs" are implicitly declared (automatically) as a result of a
140  * user declaring an extern _module_ dependency; this causes the rust driver
141  * to locate an extern crate, scan its compilation metadata, and emit extern
142  * declarations for any symbols used by the declaring crate.
143  *
144  * A "foreign" is an extern that references C (or other non-rust ABI) code.
145  * There is no metadata to scan for extern references so in these cases either
146  * a header-digester like bindgen, or manual function prototypes, have to
147  * serve as declarators. So these are usually given explicitly as prototype
148  * declarations, in rust code, with ABI attributes on them noting which ABI to
149  * link via.
150  *
151  * An "upcall" is a foreign call generated by the compiler (not corresponding
152  * to any user-written call in the code) into the runtime library, to perform
153  * some helper task such as bringing a task to life, allocating memory, etc.
154  *
155  */
156
157 #[deriving(Copy)]
158 pub struct NodeInfo {
159     pub id: ast::NodeId,
160     pub span: Span,
161 }
162
163 pub fn expr_info(expr: &ast::Expr) -> NodeInfo {
164     NodeInfo { id: expr.id, span: expr.span }
165 }
166
167 pub struct BuilderRef_res {
168     pub b: BuilderRef,
169 }
170
171 impl Drop for BuilderRef_res {
172     fn drop(&mut self) {
173         unsafe {
174             llvm::LLVMDisposeBuilder(self.b);
175         }
176     }
177 }
178
179 pub fn BuilderRef_res(b: BuilderRef) -> BuilderRef_res {
180     BuilderRef_res {
181         b: b
182     }
183 }
184
185 pub type ExternMap = FnvHashMap<String, ValueRef>;
186
187 pub fn validate_substs(substs: &Substs) {
188     assert!(substs.types.all(|t| !ty::type_needs_infer(*t)));
189 }
190
191 // work around bizarre resolve errors
192 pub type RvalueDatum<'tcx> = datum::Datum<'tcx, datum::Rvalue>;
193 pub type LvalueDatum<'tcx> = datum::Datum<'tcx, datum::Lvalue>;
194
195 // Function context.  Every LLVM function we create will have one of
196 // these.
197 pub struct FunctionContext<'a, 'tcx: 'a> {
198     // The ValueRef returned from a call to llvm::LLVMAddFunction; the
199     // address of the first instruction in the sequence of
200     // instructions for this function that will go in the .text
201     // section of the executable we're generating.
202     pub llfn: ValueRef,
203
204     // The environment argument in a closure.
205     pub llenv: Option<ValueRef>,
206
207     // A pointer to where to store the return value. If the return type is
208     // immediate, this points to an alloca in the function. Otherwise, it's a
209     // pointer to the hidden first parameter of the function. After function
210     // construction, this should always be Some.
211     pub llretslotptr: Cell<Option<ValueRef>>,
212
213     // These pub elements: "hoisted basic blocks" containing
214     // administrative activities that have to happen in only one place in
215     // the function, due to LLVM's quirks.
216     // A marker for the place where we want to insert the function's static
217     // allocas, so that LLVM will coalesce them into a single alloca call.
218     pub alloca_insert_pt: Cell<Option<ValueRef>>,
219     pub llreturn: Cell<Option<BasicBlockRef>>,
220
221     // If the function has any nested return's, including something like:
222     // fn foo() -> Option<Foo> { Some(Foo { x: return None }) }, then
223     // we use a separate alloca for each return
224     pub needs_ret_allocas: bool,
225
226     // The a value alloca'd for calls to upcalls.rust_personality. Used when
227     // outputting the resume instruction.
228     pub personality: Cell<Option<ValueRef>>,
229
230     // True if the caller expects this fn to use the out pointer to
231     // return. Either way, your code should write into the slot llretslotptr
232     // points to, but if this value is false, that slot will be a local alloca.
233     pub caller_expects_out_pointer: bool,
234
235     // Maps the DefId's for local variables to the allocas created for
236     // them in llallocas.
237     pub lllocals: RefCell<NodeMap<LvalueDatum<'tcx>>>,
238
239     // Same as above, but for closure upvars
240     pub llupvars: RefCell<NodeMap<ValueRef>>,
241
242     // The NodeId of the function, or -1 if it doesn't correspond to
243     // a user-defined function.
244     pub id: ast::NodeId,
245
246     // If this function is being monomorphized, this contains the type
247     // substitutions used.
248     pub param_substs: &'a Substs<'tcx>,
249
250     // The source span and nesting context where this function comes from, for
251     // error reporting and symbol generation.
252     pub span: Option<Span>,
253
254     // The arena that blocks are allocated from.
255     pub block_arena: &'a TypedArena<BlockS<'a, 'tcx>>,
256
257     // This function's enclosing crate context.
258     pub ccx: &'a CrateContext<'a, 'tcx>,
259
260     // Used and maintained by the debuginfo module.
261     pub debug_context: debuginfo::FunctionDebugContext,
262
263     // Cleanup scopes.
264     pub scopes: RefCell<Vec<cleanup::CleanupScope<'a, 'tcx>>>,
265 }
266
267 impl<'a, 'tcx> FunctionContext<'a, 'tcx> {
268     pub fn arg_pos(&self, arg: uint) -> uint {
269         let arg = self.env_arg_pos() + arg;
270         if self.llenv.is_some() {
271             arg + 1
272         } else {
273             arg
274         }
275     }
276
277     pub fn env_arg_pos(&self) -> uint {
278         if self.caller_expects_out_pointer {
279             1u
280         } else {
281             0u
282         }
283     }
284
285     pub fn cleanup(&self) {
286         unsafe {
287             llvm::LLVMInstructionEraseFromParent(self.alloca_insert_pt
288                                                      .get()
289                                                      .unwrap());
290         }
291     }
292
293     pub fn get_llreturn(&self) -> BasicBlockRef {
294         if self.llreturn.get().is_none() {
295
296             self.llreturn.set(Some(unsafe {
297                 "return".with_c_str(|buf| {
298                     llvm::LLVMAppendBasicBlockInContext(self.ccx.llcx(), self.llfn, buf)
299                 })
300             }))
301         }
302
303         self.llreturn.get().unwrap()
304     }
305
306     pub fn get_ret_slot(&self, bcx: Block<'a, 'tcx>,
307                         output: ty::FnOutput<'tcx>,
308                         name: &str) -> ValueRef {
309         if self.needs_ret_allocas {
310             base::alloca_no_lifetime(bcx, match output {
311                 ty::FnConverging(output_type) => type_of::type_of(bcx.ccx(), output_type),
312                 ty::FnDiverging => Type::void(bcx.ccx())
313             }, name)
314         } else {
315             self.llretslotptr.get().unwrap()
316         }
317     }
318
319     pub fn new_block(&'a self,
320                      is_lpad: bool,
321                      name: &str,
322                      opt_node_id: Option<ast::NodeId>)
323                      -> Block<'a, 'tcx> {
324         unsafe {
325             let llbb = name.with_c_str(|buf| {
326                     llvm::LLVMAppendBasicBlockInContext(self.ccx.llcx(),
327                                                         self.llfn,
328                                                         buf)
329                 });
330             BlockS::new(llbb, is_lpad, opt_node_id, self)
331         }
332     }
333
334     pub fn new_id_block(&'a self,
335                         name: &str,
336                         node_id: ast::NodeId)
337                         -> Block<'a, 'tcx> {
338         self.new_block(false, name, Some(node_id))
339     }
340
341     pub fn new_temp_block(&'a self,
342                           name: &str)
343                           -> Block<'a, 'tcx> {
344         self.new_block(false, name, None)
345     }
346
347     pub fn join_blocks(&'a self,
348                        id: ast::NodeId,
349                        in_cxs: &[Block<'a, 'tcx>])
350                        -> Block<'a, 'tcx> {
351         let out = self.new_id_block("join", id);
352         let mut reachable = false;
353         for bcx in in_cxs.iter() {
354             if !bcx.unreachable.get() {
355                 build::Br(*bcx, out.llbb);
356                 reachable = true;
357             }
358         }
359         if !reachable {
360             build::Unreachable(out);
361         }
362         return out;
363     }
364 }
365
366 // Basic block context.  We create a block context for each basic block
367 // (single-entry, single-exit sequence of instructions) we generate from Rust
368 // code.  Each basic block we generate is attached to a function, typically
369 // with many basic blocks per function.  All the basic blocks attached to a
370 // function are organized as a directed graph.
371 pub struct BlockS<'blk, 'tcx: 'blk> {
372     // The BasicBlockRef returned from a call to
373     // llvm::LLVMAppendBasicBlock(llfn, name), which adds a basic
374     // block to the function pointed to by llfn.  We insert
375     // instructions into that block by way of this block context.
376     // The block pointing to this one in the function's digraph.
377     pub llbb: BasicBlockRef,
378     pub terminated: Cell<bool>,
379     pub unreachable: Cell<bool>,
380
381     // Is this block part of a landing pad?
382     pub is_lpad: bool,
383
384     // AST node-id associated with this block, if any. Used for
385     // debugging purposes only.
386     pub opt_node_id: Option<ast::NodeId>,
387
388     // The function context for the function to which this block is
389     // attached.
390     pub fcx: &'blk FunctionContext<'blk, 'tcx>,
391 }
392
393 pub type Block<'blk, 'tcx> = &'blk BlockS<'blk, 'tcx>;
394
395 impl<'blk, 'tcx> BlockS<'blk, 'tcx> {
396     pub fn new(llbb: BasicBlockRef,
397                is_lpad: bool,
398                opt_node_id: Option<ast::NodeId>,
399                fcx: &'blk FunctionContext<'blk, 'tcx>)
400                -> Block<'blk, 'tcx> {
401         fcx.block_arena.alloc(BlockS {
402             llbb: llbb,
403             terminated: Cell::new(false),
404             unreachable: Cell::new(false),
405             is_lpad: is_lpad,
406             opt_node_id: opt_node_id,
407             fcx: fcx
408         })
409     }
410
411     pub fn ccx(&self) -> &'blk CrateContext<'blk, 'tcx> {
412         self.fcx.ccx
413     }
414     pub fn tcx(&self) -> &'blk ty::ctxt<'tcx> {
415         self.fcx.ccx.tcx()
416     }
417     pub fn sess(&self) -> &'blk Session { self.fcx.ccx.sess() }
418
419     pub fn ident(&self, ident: Ident) -> String {
420         token::get_ident(ident).get().to_string()
421     }
422
423     pub fn node_id_to_string(&self, id: ast::NodeId) -> String {
424         self.tcx().map.node_to_string(id).to_string()
425     }
426
427     pub fn expr_to_string(&self, e: &ast::Expr) -> String {
428         e.repr(self.tcx())
429     }
430
431     pub fn def(&self, nid: ast::NodeId) -> def::Def {
432         match self.tcx().def_map.borrow().get(&nid) {
433             Some(v) => v.clone(),
434             None => {
435                 self.tcx().sess.bug(format!(
436                     "no def associated with node id {}", nid).as_slice());
437             }
438         }
439     }
440
441     pub fn val_to_string(&self, val: ValueRef) -> String {
442         self.ccx().tn().val_to_string(val)
443     }
444
445     pub fn llty_str(&self, ty: Type) -> String {
446         self.ccx().tn().type_to_string(ty)
447     }
448
449     pub fn ty_to_string(&self, t: Ty<'tcx>) -> String {
450         t.repr(self.tcx())
451     }
452
453     pub fn to_str(&self) -> String {
454         format!("[block {:p}]", self)
455     }
456 }
457
458 impl<'blk, 'tcx> mc::Typer<'tcx> for BlockS<'blk, 'tcx> {
459     fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx> {
460         self.tcx()
461     }
462
463     fn node_ty(&self, id: ast::NodeId) -> mc::McResult<Ty<'tcx>> {
464         Ok(node_id_type(self, id))
465     }
466
467     fn node_method_ty(&self, method_call: ty::MethodCall) -> Option<Ty<'tcx>> {
468         self.tcx()
469             .method_map
470             .borrow()
471             .get(&method_call)
472             .map(|method| monomorphize_type(self, method.ty))
473     }
474
475     fn adjustments<'a>(&'a self) -> &'a RefCell<NodeMap<ty::AutoAdjustment<'tcx>>> {
476         &self.tcx().adjustments
477     }
478
479     fn is_method_call(&self, id: ast::NodeId) -> bool {
480         self.tcx().method_map.borrow().contains_key(&ty::MethodCall::expr(id))
481     }
482
483     fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<region::CodeExtent> {
484         self.tcx().region_maps.temporary_scope(rvalue_id)
485     }
486
487     fn unboxed_closures<'a>(&'a self)
488                         -> &'a RefCell<DefIdMap<ty::UnboxedClosure<'tcx>>> {
489         &self.tcx().unboxed_closures
490     }
491
492     fn upvar_borrow(&self, upvar_id: ty::UpvarId) -> ty::UpvarBorrow {
493         self.tcx().upvar_borrow_map.borrow()[upvar_id].clone()
494     }
495
496     fn capture_mode(&self, closure_expr_id: ast::NodeId)
497                     -> ast::CaptureClause {
498         self.tcx().capture_modes.borrow()[closure_expr_id].clone()
499     }
500 }
501
502 pub struct Result<'blk, 'tcx: 'blk> {
503     pub bcx: Block<'blk, 'tcx>,
504     pub val: ValueRef
505 }
506
507 impl<'b, 'tcx> Result<'b, 'tcx> {
508     pub fn new(bcx: Block<'b, 'tcx>, val: ValueRef) -> Result<'b, 'tcx> {
509         Result {
510             bcx: bcx,
511             val: val,
512         }
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::i1(ccx), val as u64, false)
553 }
554
555 pub fn C_i32(ccx: &CrateContext, i: i32) -> ValueRef {
556     C_integral(Type::i32(ccx), i as u64, true)
557 }
558
559 pub fn C_i64(ccx: &CrateContext, i: i64) -> ValueRef {
560     C_integral(Type::i64(ccx), i as u64, true)
561 }
562
563 pub fn C_u64(ccx: &CrateContext, i: u64) -> ValueRef {
564     C_integral(Type::i64(ccx), i, false)
565 }
566
567 pub fn C_int<I: AsI64>(ccx: &CrateContext, i: I) -> ValueRef {
568     let v = i.as_i64();
569
570     match machine::llbitsize_of_real(ccx, ccx.int_type()) {
571         32 => assert!(v < (1<<31) && v >= -(1<<31)),
572         64 => {},
573         n => panic!("unsupported target size: {}", n)
574     }
575
576     C_integral(ccx.int_type(), v as u64, true)
577 }
578
579 pub fn C_uint<I: AsU64>(ccx: &CrateContext, i: I) -> ValueRef {
580     let v = i.as_u64();
581
582     match machine::llbitsize_of_real(ccx, ccx.int_type()) {
583         32 => assert!(v < (1<<32)),
584         64 => {},
585         n => panic!("unsupported target size: {}", n)
586     }
587
588     C_integral(ccx.int_type(), v, false)
589 }
590
591 pub trait AsI64 { fn as_i64(self) -> i64; }
592 pub trait AsU64 { fn as_u64(self) -> u64; }
593
594 // FIXME: remove the intptr conversions, because they
595 // are host-architecture-dependent
596 impl AsI64 for i64 { fn as_i64(self) -> i64 { self as i64 }}
597 impl AsI64 for i32 { fn as_i64(self) -> i64 { self as i64 }}
598 impl AsI64 for int { fn as_i64(self) -> i64 { self as i64 }}
599
600 impl AsU64 for u64  { fn as_u64(self) -> u64 { self as u64 }}
601 impl AsU64 for u32  { fn as_u64(self) -> u64 { self as u64 }}
602 impl AsU64 for uint { fn as_u64(self) -> u64 { self as u64 }}
603
604 pub fn C_u8(ccx: &CrateContext, i: uint) -> ValueRef {
605     C_integral(Type::i8(ccx), i as u64, false)
606 }
607
608
609 // This is a 'c-like' raw string, which differs from
610 // our boxed-and-length-annotated strings.
611 pub fn C_cstr(cx: &CrateContext, s: InternedString, null_terminated: bool) -> ValueRef {
612     unsafe {
613         match cx.const_cstr_cache().borrow().get(&s) {
614             Some(&llval) => return llval,
615             None => ()
616         }
617
618         let sc = llvm::LLVMConstStringInContext(cx.llcx(),
619                                                 s.get().as_ptr() as *const c_char,
620                                                 s.get().len() as c_uint,
621                                                 !null_terminated as Bool);
622
623         let gsym = token::gensym("str");
624         let g = format!("str{}", gsym.uint()).with_c_str(|buf| {
625             llvm::LLVMAddGlobal(cx.llmod(), val_ty(sc).to_ref(), buf)
626         });
627         llvm::LLVMSetInitializer(g, sc);
628         llvm::LLVMSetGlobalConstant(g, True);
629         llvm::SetLinkage(g, llvm::InternalLinkage);
630
631         cx.const_cstr_cache().borrow_mut().insert(s, g);
632         g
633     }
634 }
635
636 // NB: Do not use `do_spill_noroot` to make this into a constant string, or
637 // you will be kicked off fast isel. See issue #4352 for an example of this.
638 pub fn C_str_slice(cx: &CrateContext, s: InternedString) -> ValueRef {
639     unsafe {
640         let len = s.get().len();
641         let cs = llvm::LLVMConstPointerCast(C_cstr(cx, s, false),
642                                             Type::i8p(cx).to_ref());
643         C_named_struct(cx.tn().find_type("str_slice").unwrap(), &[cs, C_uint(cx, len)])
644     }
645 }
646
647 pub fn C_binary_slice(cx: &CrateContext, data: &[u8]) -> ValueRef {
648     unsafe {
649         let len = data.len();
650         let lldata = C_bytes(cx, data);
651
652         let gsym = token::gensym("binary");
653         let g = format!("binary{}", gsym.uint()).with_c_str(|buf| {
654             llvm::LLVMAddGlobal(cx.llmod(), val_ty(lldata).to_ref(), buf)
655         });
656         llvm::LLVMSetInitializer(g, lldata);
657         llvm::LLVMSetGlobalConstant(g, True);
658         llvm::SetLinkage(g, llvm::InternalLinkage);
659
660         let cs = llvm::LLVMConstPointerCast(g, Type::i8p(cx).to_ref());
661         C_struct(cx, &[cs, C_uint(cx, len)], false)
662     }
663 }
664
665 pub fn C_struct(cx: &CrateContext, elts: &[ValueRef], packed: bool) -> ValueRef {
666     C_struct_in_context(cx.llcx(), elts, packed)
667 }
668
669 pub fn C_struct_in_context(llcx: ContextRef, elts: &[ValueRef], packed: bool) -> ValueRef {
670     unsafe {
671         llvm::LLVMConstStructInContext(llcx,
672                                        elts.as_ptr(), elts.len() as c_uint,
673                                        packed as Bool)
674     }
675 }
676
677 pub fn C_named_struct(t: Type, elts: &[ValueRef]) -> ValueRef {
678     unsafe {
679         llvm::LLVMConstNamedStruct(t.to_ref(), elts.as_ptr(), elts.len() as c_uint)
680     }
681 }
682
683 pub fn C_array(ty: Type, elts: &[ValueRef]) -> ValueRef {
684     unsafe {
685         return llvm::LLVMConstArray(ty.to_ref(), elts.as_ptr(), elts.len() as c_uint);
686     }
687 }
688
689 pub fn C_bytes(cx: &CrateContext, bytes: &[u8]) -> ValueRef {
690     C_bytes_in_context(cx.llcx(), bytes)
691 }
692
693 pub fn C_bytes_in_context(llcx: ContextRef, bytes: &[u8]) -> ValueRef {
694     unsafe {
695         let ptr = bytes.as_ptr() as *const c_char;
696         return llvm::LLVMConstStringInContext(llcx, ptr, bytes.len() as c_uint, True);
697     }
698 }
699
700 pub fn const_get_elt(cx: &CrateContext, v: ValueRef, us: &[c_uint])
701                   -> ValueRef {
702     unsafe {
703         let r = llvm::LLVMConstExtractValue(v, us.as_ptr(), us.len() as c_uint);
704
705         debug!("const_get_elt(v={}, us={}, r={})",
706                cx.tn().val_to_string(v), us, cx.tn().val_to_string(r));
707
708         return r;
709     }
710 }
711
712 pub fn is_const(v: ValueRef) -> bool {
713     unsafe {
714         llvm::LLVMIsConstant(v) == True
715     }
716 }
717
718 pub fn const_to_int(v: ValueRef) -> i64 {
719     unsafe {
720         llvm::LLVMConstIntGetSExtValue(v)
721     }
722 }
723
724 pub fn const_to_uint(v: ValueRef) -> u64 {
725     unsafe {
726         llvm::LLVMConstIntGetZExtValue(v)
727     }
728 }
729
730 pub fn is_undef(val: ValueRef) -> bool {
731     unsafe {
732         llvm::LLVMIsUndef(val) != False
733     }
734 }
735
736 pub fn is_null(val: ValueRef) -> bool {
737     unsafe {
738         llvm::LLVMIsNull(val) != False
739     }
740 }
741
742 pub fn monomorphize_type<'blk, 'tcx>(bcx: &BlockS<'blk, 'tcx>, t: Ty<'tcx>) -> Ty<'tcx> {
743     t.subst(bcx.tcx(), bcx.fcx.param_substs)
744 }
745
746 pub fn node_id_type<'blk, 'tcx>(bcx: &BlockS<'blk, 'tcx>, id: ast::NodeId) -> Ty<'tcx> {
747     let tcx = bcx.tcx();
748     let t = ty::node_id_to_type(tcx, id);
749     monomorphize_type(bcx, t)
750 }
751
752 pub fn expr_ty<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ex: &ast::Expr) -> Ty<'tcx> {
753     node_id_type(bcx, ex.id)
754 }
755
756 pub fn expr_ty_adjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ex: &ast::Expr) -> Ty<'tcx> {
757     monomorphize_type(bcx, ty::expr_ty_adjusted(bcx.tcx(), ex))
758 }
759
760 /// Attempts to resolve an obligation. The result is a shallow vtable resolution -- meaning that we
761 /// do not (necessarily) resolve all nested obligations on the impl. Note that type check should
762 /// guarantee to us that all nested obligations *could be* resolved if we wanted to.
763 pub fn fulfill_obligation<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
764                                     span: Span,
765                                     trait_ref: Rc<ty::PolyTraitRef<'tcx>>)
766                                     -> traits::Vtable<'tcx, ()>
767 {
768     let tcx = ccx.tcx();
769
770     // Remove any references to regions; this helps improve caching.
771     let trait_ref = ty_fold::erase_regions(tcx, trait_ref);
772
773     // First check the cache.
774     match ccx.trait_cache().borrow().get(&trait_ref) {
775         Some(vtable) => {
776             info!("Cache hit: {}", trait_ref.repr(ccx.tcx()));
777             return (*vtable).clone();
778         }
779         None => { }
780     }
781
782     debug!("trans fulfill_obligation: trait_ref={}", trait_ref.repr(ccx.tcx()));
783
784     ty::populate_implementations_for_trait_if_necessary(tcx, trait_ref.def_id());
785     let infcx = infer::new_infer_ctxt(tcx);
786
787     // Parameter environment is used to give details about type parameters,
788     // but since we are in trans, everything is fully monomorphized.
789     let param_env = ty::empty_parameter_environment();
790
791     // Do the initial selection for the obligation. This yields the
792     // shallow result we are looking for -- that is, what specific impl.
793     let mut selcx = traits::SelectionContext::new(&infcx, &param_env, tcx);
794     let obligation = traits::Obligation::new(traits::ObligationCause::dummy(),
795                                              trait_ref.clone());
796     let selection = match selcx.select(&obligation) {
797         Ok(Some(selection)) => selection,
798         Ok(None) => {
799             // Ambiguity can happen when monomorphizing during trans
800             // expands to some humongo type that never occurred
801             // statically -- this humongo type can then overflow,
802             // leading to an ambiguous result. So report this as an
803             // overflow bug, since I believe this is the only case
804             // where ambiguity can result.
805             debug!("Encountered ambiguity selecting `{}` during trans, \
806                     presuming due to overflow",
807                    trait_ref.repr(tcx));
808             ccx.sess().span_fatal(
809                 span,
810                 "reached the recursion limit during monomorphization");
811         }
812         Err(e) => {
813             tcx.sess.span_bug(
814                 span,
815                 format!("Encountered error `{}` selecting `{}` during trans",
816                         e.repr(tcx),
817                         trait_ref.repr(tcx)).as_slice())
818         }
819     };
820
821     // Currently, we use a fulfillment context to completely resolve
822     // all nested obligations. This is because they can inform the
823     // inference of the impl's type parameters. However, in principle,
824     // we only need to do this until the impl's type parameters are
825     // fully bound. It could be a slight optimization to stop
826     // iterating early.
827     let mut fulfill_cx = traits::FulfillmentContext::new();
828     let vtable = selection.map_move_nested(|predicate| {
829         fulfill_cx.register_predicate(infcx.tcx, predicate);
830     });
831     match fulfill_cx.select_all_or_error(&infcx, &param_env, tcx) {
832         Ok(()) => { }
833         Err(errors) => {
834             if errors.iter().all(|e| e.is_overflow()) {
835                 // See Ok(None) case above.
836                 ccx.sess().span_fatal(
837                     span,
838                     "reached the recursion limit during monomorphization");
839             } else {
840                 tcx.sess.span_bug(
841                     span,
842                     format!("Encountered errors `{}` fulfilling `{}` during trans",
843                             errors.repr(tcx),
844                             trait_ref.repr(tcx)).as_slice());
845             }
846         }
847     }
848
849     // Use freshen to simultaneously replace all type variables with
850     // their bindings and replace all regions with 'static.  This is
851     // sort of overkill because we do not expect there to be any
852     // unbound type variables, hence no `TyFresh` types should ever be
853     // inserted.
854     let vtable = vtable.fold_with(&mut infcx.freshener());
855
856     info!("Cache miss: {}", trait_ref.repr(ccx.tcx()));
857     ccx.trait_cache().borrow_mut().insert(trait_ref,
858                                           vtable.clone());
859
860     vtable
861 }
862
863 // Key used to lookup values supplied for type parameters in an expr.
864 #[deriving(Copy, PartialEq, Show)]
865 pub enum ExprOrMethodCall {
866     // Type parameters for a path like `None::<int>`
867     ExprId(ast::NodeId),
868
869     // Type parameters for a method call like `a.foo::<int>()`
870     MethodCall(ty::MethodCall)
871 }
872
873 pub fn node_id_substs<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
874                                   node: ExprOrMethodCall)
875                                   -> subst::Substs<'tcx> {
876     let tcx = bcx.tcx();
877
878     let substs = match node {
879         ExprId(id) => {
880             ty::node_id_item_substs(tcx, id).substs
881         }
882         MethodCall(method_call) => {
883             (*tcx.method_map.borrow())[method_call].substs.clone()
884         }
885     };
886
887     if substs.types.any(|t| ty::type_needs_infer(*t)) {
888         bcx.sess().bug(
889             format!("type parameters for node {} include inference types: \
890                      {}",
891                     node,
892                     substs.repr(bcx.tcx())).as_slice());
893     }
894
895     let substs = substs.erase_regions();
896     substs.subst(tcx, bcx.fcx.param_substs)
897 }
898
899 pub fn langcall(bcx: Block,
900                 span: Option<Span>,
901                 msg: &str,
902                 li: LangItem)
903                 -> ast::DefId {
904     match bcx.tcx().lang_items.require(li) {
905         Ok(id) => id,
906         Err(s) => {
907             let msg = format!("{} {}", msg, s);
908             match span {
909                 Some(span) => bcx.tcx().sess.span_fatal(span, msg.as_slice()),
910                 None => bcx.tcx().sess.fatal(msg.as_slice()),
911             }
912         }
913     }
914 }