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