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