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