]> git.lizzy.rs Git - rust.git/blob - src/librustc/middle/trans/common.rs
f8fb0f4b7cf318f6b2194637873789b1eaeacc09
[rust.git] / src / librustc / middle / trans / common.rs
1 // Copyright 2012-2013 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
12 /**
13    Code that is useful in various trans modules.
14
15 */
16
17 use back::{abi, upcall};
18 use driver::session;
19 use driver::session::Session;
20 use lib::llvm::{ModuleRef, ValueRef, TypeRef, BasicBlockRef, BuilderRef};
21 use lib::llvm::{True, False, Bool};
22 use lib::llvm::{llvm, TargetData, TypeNames, associate_type, name_has_type};
23 use lib;
24 use metadata::common::LinkMeta;
25 use middle::astencode;
26 use middle::resolve;
27 use middle::trans::adt;
28 use middle::trans::base;
29 use middle::trans::build;
30 use middle::trans::callee;
31 use middle::trans::datum;
32 use middle::trans::debuginfo;
33 use middle::trans::expr;
34 use middle::trans::glue;
35 use middle::trans::reachable;
36 use middle::trans::shape;
37 use middle::trans::type_of;
38 use middle::trans::type_use;
39 use middle::ty::substs;
40 use middle::ty;
41 use middle::typeck;
42 use util::ppaux::{Repr};
43
44 use core::cast::transmute;
45 use core::hash;
46 use core::hashmap::{HashMap, HashSet};
47 use core::libc::{c_uint, c_longlong, c_ulonglong};
48 use core::to_bytes;
49 use core::vec::raw::to_ptr;
50 use syntax::ast::ident;
51 use syntax::ast_map::{path, path_elt};
52 use syntax::codemap::span;
53 use syntax::parse::token::ident_interner;
54 use syntax::{ast, ast_map};
55 use syntax::abi::{X86, X86_64, Arm, Mips};
56
57 pub type namegen = @fn(s: ~str) -> ident;
58 pub fn new_namegen(intr: @ident_interner) -> namegen {
59     let f: @fn(s: ~str) -> ident = |prefix| {
60         intr.gensym(@fmt!("%s_%u",
61                           prefix,
62                           intr.gensym(@prefix).repr))
63     };
64     f
65 }
66
67 pub type addrspace = c_uint;
68
69 // Address spaces communicate to LLVM which destructors need to run for
70 // specific types.
71 //    0 is ignored by the GC, and is used for all non-GC'd pointers.
72 //    1 is for opaque GC'd boxes.
73 //    >= 2 are for specific types (e.g. resources).
74 pub static default_addrspace: addrspace = 0;
75 pub static gc_box_addrspace: addrspace = 1;
76
77 pub type addrspace_gen = @fn() -> addrspace;
78 pub fn new_addrspace_gen() -> addrspace_gen {
79     let i = @mut 1;
80     let result: addrspace_gen = || { *i += 1; *i };
81     result
82 }
83
84 pub struct tydesc_info {
85     ty: ty::t,
86     tydesc: ValueRef,
87     size: ValueRef,
88     align: ValueRef,
89     addrspace: addrspace,
90     take_glue: Option<ValueRef>,
91     drop_glue: Option<ValueRef>,
92     free_glue: Option<ValueRef>,
93     visit_glue: Option<ValueRef>
94 }
95
96 /*
97  * A note on nomenclature of linking: "extern", "foreign", and "upcall".
98  *
99  * An "extern" is an LLVM symbol we wind up emitting an undefined external
100  * reference to. This means "we don't have the thing in this compilation unit,
101  * please make sure you link it in at runtime". This could be a reference to
102  * C code found in a C library, or rust code found in a rust crate.
103  *
104  * Most "externs" are implicitly declared (automatically) as a result of a
105  * user declaring an extern _module_ dependency; this causes the rust driver
106  * to locate an extern crate, scan its compilation metadata, and emit extern
107  * declarations for any symbols used by the declaring crate.
108  *
109  * A "foreign" is an extern that references C (or other non-rust ABI) code.
110  * There is no metadata to scan for extern references so in these cases either
111  * a header-digester like bindgen, or manual function prototypes, have to
112  * serve as declarators. So these are usually given explicitly as prototype
113  * declarations, in rust code, with ABI attributes on them noting which ABI to
114  * link via.
115  *
116  * An "upcall" is a foreign call generated by the compiler (not corresponding
117  * to any user-written call in the code) into the runtime library, to perform
118  * some helper task such as bringing a task to life, allocating memory, etc.
119  *
120  */
121
122 pub struct Stats {
123     n_static_tydescs: uint,
124     n_glues_created: uint,
125     n_null_glues: uint,
126     n_real_glues: uint,
127     n_fns: uint,
128     n_monos: uint,
129     n_inlines: uint,
130     n_closures: uint,
131     llvm_insn_ctxt: @mut ~[~str],
132     llvm_insns: @mut HashMap<~str, uint>,
133     fn_times: @mut ~[(~str, int)] // (ident, time)
134 }
135
136 pub struct BuilderRef_res {
137     B: BuilderRef,
138 }
139
140 impl Drop for BuilderRef_res {
141     fn finalize(&self) {
142         unsafe {
143             llvm::LLVMDisposeBuilder(self.B);
144         }
145     }
146 }
147
148 pub fn BuilderRef_res(B: BuilderRef) -> BuilderRef_res {
149     BuilderRef_res {
150         B: B
151     }
152 }
153
154 pub type ExternMap = @mut HashMap<@str, ValueRef>;
155
156 // Crate context.  Every crate we compile has one of these.
157 pub struct CrateContext {
158      sess: session::Session,
159      llmod: ModuleRef,
160      td: TargetData,
161      tn: @TypeNames,
162      externs: ExternMap,
163      intrinsics: HashMap<~str, ValueRef>,
164      item_vals: @mut HashMap<ast::node_id, ValueRef>,
165      exp_map2: resolve::ExportMap2,
166      reachable: reachable::map,
167      item_symbols: @mut HashMap<ast::node_id, ~str>,
168      link_meta: LinkMeta,
169      enum_sizes: @mut HashMap<ty::t, uint>,
170      discrims: @mut HashMap<ast::def_id, ValueRef>,
171      discrim_symbols: @mut HashMap<ast::node_id, @~str>,
172      tydescs: @mut HashMap<ty::t, @mut tydesc_info>,
173      // Set when running emit_tydescs to enforce that no more tydescs are
174      // created.
175      finished_tydescs: @mut bool,
176      // Track mapping of external ids to local items imported for inlining
177      external: @mut HashMap<ast::def_id, Option<ast::node_id>>,
178      // Cache instances of monomorphized functions
179      monomorphized: @mut HashMap<mono_id, ValueRef>,
180      monomorphizing: @mut HashMap<ast::def_id, uint>,
181      // Cache computed type parameter uses (see type_use.rs)
182      type_use_cache: @mut HashMap<ast::def_id, @~[type_use::type_uses]>,
183      // Cache generated vtables
184      vtables: @mut HashMap<mono_id, ValueRef>,
185      // Cache of constant strings,
186      const_cstr_cache: @mut HashMap<@~str, ValueRef>,
187
188      // Reverse-direction for const ptrs cast from globals.
189      // Key is an int, cast from a ValueRef holding a *T,
190      // Val is a ValueRef holding a *[T].
191      //
192      // Needed because LLVM loses pointer->pointee association
193      // when we ptrcast, and we have to ptrcast during translation
194      // of a [T] const because we form a slice, a [*T,int] pair, not
195      // a pointer to an LLVM array type.
196      const_globals: @mut HashMap<int, ValueRef>,
197
198      // Cache of emitted const values
199      const_values: @mut HashMap<ast::node_id, ValueRef>,
200
201      // Cache of external const values
202      extern_const_values: @mut HashMap<ast::def_id, ValueRef>,
203
204      module_data: @mut HashMap<~str, ValueRef>,
205      lltypes: @mut HashMap<ty::t, TypeRef>,
206      llsizingtypes: @mut HashMap<ty::t, TypeRef>,
207      adt_reprs: @mut HashMap<ty::t, @adt::Repr>,
208      names: namegen,
209      next_addrspace: addrspace_gen,
210      symbol_hasher: @hash::State,
211      type_hashcodes: @mut HashMap<ty::t, @str>,
212      type_short_names: @mut HashMap<ty::t, ~str>,
213      all_llvm_symbols: @mut HashSet<@~str>,
214      tcx: ty::ctxt,
215      maps: astencode::Maps,
216      stats: @mut Stats,
217      upcalls: @upcall::Upcalls,
218      tydesc_type: TypeRef,
219      int_type: TypeRef,
220      float_type: TypeRef,
221      task_type: TypeRef,
222      opaque_vec_type: TypeRef,
223      builder: BuilderRef_res,
224      shape_cx: shape::Ctxt,
225      crate_map: ValueRef,
226      // Set when at least one function uses GC. Needed so that
227      // decl_gc_metadata knows whether to link to the module metadata, which
228      // is not emitted by LLVM's GC pass when no functions use GC.
229      uses_gc: @mut bool,
230      dbg_cx: Option<debuginfo::DebugContext>,
231      do_not_commit_warning_issued: @mut bool
232 }
233
234 // Types used for llself.
235 pub struct ValSelfData {
236     v: ValueRef,
237     t: ty::t,
238     is_owned: bool
239 }
240
241 pub enum local_val { local_mem(ValueRef), local_imm(ValueRef), }
242
243 // Here `self_ty` is the real type of the self parameter to this method. It
244 // will only be set in the case of default methods.
245 pub struct param_substs {
246     tys: ~[ty::t],
247     vtables: Option<typeck::vtable_res>,
248     type_param_defs: @~[ty::TypeParameterDef],
249     self_ty: Option<ty::t>
250 }
251
252 pub impl param_substs {
253     fn validate(&self) {
254         for self.tys.each |t| { assert!(!ty::type_needs_infer(*t)); }
255         for self.self_ty.each |t| { assert!(!ty::type_needs_infer(*t)); }
256     }
257 }
258
259 fn param_substs_to_str(self: &param_substs,
260                        tcx: ty::ctxt) -> ~str
261 {
262     fmt!("param_substs {tys:%s, vtables:%s, type_param_defs:%s}",
263          self.tys.repr(tcx),
264          self.vtables.repr(tcx),
265          self.type_param_defs.repr(tcx))
266 }
267
268 impl Repr for param_substs {
269     fn repr(&self, tcx: ty::ctxt) -> ~str {
270         param_substs_to_str(self, tcx)
271     }
272 }
273
274 impl Repr for @param_substs {
275     fn repr(&self, tcx: ty::ctxt) -> ~str {
276         param_substs_to_str(*self, tcx)
277     }
278 }
279
280 // Function context.  Every LLVM function we create will have one of
281 // these.
282 pub struct fn_ctxt_ {
283     // The ValueRef returned from a call to llvm::LLVMAddFunction; the
284     // address of the first instruction in the sequence of
285     // instructions for this function that will go in the .text
286     // section of the executable we're generating.
287     llfn: ValueRef,
288
289     // The implicit environment argument that arrives in the function we're
290     // creating.
291     llenv: ValueRef,
292
293     // The place to store the return value. If the return type is immediate,
294     // this is an alloca in the function. Otherwise, it's the hidden first
295     // parameter to the function. After function construction, this should
296     // always be Some.
297     llretptr: Option<ValueRef>,
298
299     // These elements: "hoisted basic blocks" containing
300     // administrative activities that have to happen in only one place in
301     // the function, due to LLVM's quirks.
302     // A block for all the function's static allocas, so that LLVM
303     // will coalesce them into a single alloca call.
304     llstaticallocas: BasicBlockRef,
305     // A block containing code that copies incoming arguments to space
306     // already allocated by code in one of the llallocas blocks.
307     // (LLVM requires that arguments be copied to local allocas before
308     // allowing most any operation to be performed on them.)
309     llloadenv: Option<BasicBlockRef>,
310     llreturn: BasicBlockRef,
311     // The 'self' value currently in use in this function, if there
312     // is one.
313     //
314     // NB: This is the type of the self *variable*, not the self *type*. The
315     // self type is set only for default methods, while the self variable is
316     // set for all methods.
317     llself: Option<ValSelfData>,
318     // The a value alloca'd for calls to upcalls.rust_personality. Used when
319     // outputting the resume instruction.
320     personality: Option<ValueRef>,
321     // If this is a for-loop body that returns, this holds the pointers needed
322     // for that (flagptr, retptr)
323     loop_ret: Option<(ValueRef, ValueRef)>,
324
325     // True if this function has an immediate return value, false otherwise.
326     // If this is false, the llretptr will alias the first argument of the
327     // function.
328     has_immediate_return_value: bool,
329
330     // Maps arguments to allocas created for them in llallocas.
331     llargs: @mut HashMap<ast::node_id, local_val>,
332     // Maps the def_ids for local variables to the allocas created for
333     // them in llallocas.
334     lllocals: @mut HashMap<ast::node_id, local_val>,
335     // Same as above, but for closure upvars
336     llupvars: @mut HashMap<ast::node_id, ValueRef>,
337
338     // The node_id of the function, or -1 if it doesn't correspond to
339     // a user-defined function.
340     id: ast::node_id,
341
342     // The def_id of the impl we're inside, or None if we aren't inside one.
343     impl_id: Option<ast::def_id>,
344
345     // If this function is being monomorphized, this contains the type
346     // substitutions used.
347     param_substs: Option<@param_substs>,
348
349     // The source span and nesting context where this function comes from, for
350     // error reporting and symbol generation.
351     span: Option<span>,
352     path: path,
353
354     // This function's enclosing crate context.
355     ccx: @@CrateContext
356 }
357
358 pub type fn_ctxt = @mut fn_ctxt_;
359
360 pub fn warn_not_to_commit(ccx: @CrateContext, msg: &str) {
361     if !*ccx.do_not_commit_warning_issued {
362         *ccx.do_not_commit_warning_issued = true;
363         ccx.sess.warn(msg.to_str() + ~" -- do not commit like this!");
364     }
365 }
366
367 // Heap selectors. Indicate which heap something should go on.
368 #[deriving(Eq)]
369 pub enum heap {
370     heap_managed,
371     heap_managed_unique,
372     heap_exchange,
373 }
374
375 #[deriving(Eq)]
376 pub enum cleantype {
377     normal_exit_only,
378     normal_exit_and_unwind
379 }
380
381 pub enum cleanup {
382     clean(@fn(block) -> block, cleantype),
383     clean_temp(ValueRef, @fn(block) -> block, cleantype),
384 }
385
386 // Used to remember and reuse existing cleanup paths
387 // target: none means the path ends in an resume instruction
388 pub struct cleanup_path {
389     target: Option<BasicBlockRef>,
390     dest: BasicBlockRef
391 }
392
393 pub fn scope_clean_changed(scope_info: &mut scope_info) {
394     if scope_info.cleanup_paths.len() > 0u { scope_info.cleanup_paths = ~[]; }
395     scope_info.landing_pad = None;
396 }
397
398 pub fn cleanup_type(cx: ty::ctxt, ty: ty::t) -> cleantype {
399     if ty::type_needs_unwind_cleanup(cx, ty) {
400         normal_exit_and_unwind
401     } else {
402         normal_exit_only
403     }
404 }
405
406 // This is not the same as datum::Datum::root(), which is used to keep copies
407 // of @ values live for as long as a borrowed pointer to the interior exists.
408 // In the new GC, we can identify immediates on the stack without difficulty,
409 // but have trouble knowing where non-immediates are on the stack. For
410 // non-immediates, we must add an additional level of indirection, which
411 // allows us to alloca a pointer with the right addrspace.
412 pub fn root_for_cleanup(bcx: block, v: ValueRef, t: ty::t)
413     -> (ValueRef, bool) {
414     let ccx = bcx.ccx();
415
416     let addrspace = base::get_tydesc(ccx, t).addrspace;
417     if addrspace > gc_box_addrspace {
418         let llty = type_of::type_of_rooted(ccx, t);
419         let root = base::alloca(bcx, llty);
420         build::Store(bcx, build::PointerCast(bcx, v, llty), root);
421         (root, true)
422     } else {
423         (v, false)
424     }
425 }
426
427 pub fn add_clean(bcx: block, val: ValueRef, t: ty::t) {
428     if !ty::type_needs_drop(bcx.tcx(), t) { return; }
429     debug!("add_clean(%s, %s, %s)",
430            bcx.to_str(),
431            val_str(bcx.ccx().tn, val),
432            t.repr(bcx.tcx()));
433     let (root, rooted) = root_for_cleanup(bcx, val, t);
434     let cleanup_type = cleanup_type(bcx.tcx(), t);
435     do in_scope_cx(bcx) |scope_info| {
436         scope_info.cleanups.push(
437             clean(|a| glue::drop_ty_root(a, root, rooted, t),
438                   cleanup_type));
439         scope_clean_changed(scope_info);
440     }
441 }
442
443 pub fn add_clean_temp_immediate(cx: block, val: ValueRef, ty: ty::t) {
444     if !ty::type_needs_drop(cx.tcx(), ty) { return; }
445     debug!("add_clean_temp_immediate(%s, %s, %s)",
446            cx.to_str(), val_str(cx.ccx().tn, val),
447            ty.repr(cx.tcx()));
448     let cleanup_type = cleanup_type(cx.tcx(), ty);
449     do in_scope_cx(cx) |scope_info| {
450         scope_info.cleanups.push(
451             clean_temp(val, |a| glue::drop_ty_immediate(a, val, ty),
452                        cleanup_type));
453         scope_clean_changed(scope_info);
454     }
455 }
456 pub fn add_clean_temp_mem(bcx: block, val: ValueRef, t: ty::t) {
457     if !ty::type_needs_drop(bcx.tcx(), t) { return; }
458     debug!("add_clean_temp_mem(%s, %s, %s)",
459            bcx.to_str(), val_str(bcx.ccx().tn, val),
460            t.repr(bcx.tcx()));
461     let (root, rooted) = root_for_cleanup(bcx, val, t);
462     let cleanup_type = cleanup_type(bcx.tcx(), t);
463     do in_scope_cx(bcx) |scope_info| {
464         scope_info.cleanups.push(
465             clean_temp(val, |a| glue::drop_ty_root(a, root, rooted, t),
466                        cleanup_type));
467         scope_clean_changed(scope_info);
468     }
469 }
470 pub fn add_clean_frozen_root(bcx: block, val: ValueRef, t: ty::t) {
471     debug!("add_clean_frozen_root(%s, %s, %s)",
472            bcx.to_str(), val_str(bcx.ccx().tn, val),
473            t.repr(bcx.tcx()));
474     let (root, rooted) = root_for_cleanup(bcx, val, t);
475     let cleanup_type = cleanup_type(bcx.tcx(), t);
476     do in_scope_cx(bcx) |scope_info| {
477         scope_info.cleanups.push(
478             clean_temp(val, |bcx| {
479                 let bcx = callee::trans_lang_call(
480                     bcx,
481                     bcx.tcx().lang_items.return_to_mut_fn(),
482                     ~[
483                         build::Load(bcx,
484                                     build::PointerCast(bcx,
485                                                        root,
486                                                        T_ptr(T_ptr(T_i8()))))
487                     ],
488                     expr::Ignore
489                 );
490                 glue::drop_ty_root(bcx, root, rooted, t)
491             }, cleanup_type));
492         scope_clean_changed(scope_info);
493     }
494 }
495 pub fn add_clean_free(cx: block, ptr: ValueRef, heap: heap) {
496     let free_fn = match heap {
497       heap_managed | heap_managed_unique => {
498         let f: @fn(block) -> block = |a| glue::trans_free(a, ptr);
499         f
500       }
501       heap_exchange => {
502         let f: @fn(block) -> block = |a| glue::trans_exchange_free(a, ptr);
503         f
504       }
505     };
506     do in_scope_cx(cx) |scope_info| {
507         scope_info.cleanups.push(clean_temp(ptr, free_fn,
508                                       normal_exit_and_unwind));
509         scope_clean_changed(scope_info);
510     }
511 }
512
513 // Note that this only works for temporaries. We should, at some point, move
514 // to a system where we can also cancel the cleanup on local variables, but
515 // this will be more involved. For now, we simply zero out the local, and the
516 // drop glue checks whether it is zero.
517 pub fn revoke_clean(cx: block, val: ValueRef) {
518     do in_scope_cx(cx) |scope_info| {
519         let cleanup_pos = vec::position(
520             scope_info.cleanups,
521             |cu| match *cu {
522                 clean_temp(v, _, _) if v == val => true,
523                 _ => false
524             });
525         for cleanup_pos.each |i| {
526             scope_info.cleanups =
527                 vec::append(vec::slice(scope_info.cleanups, 0u, *i).to_vec(),
528                             vec::slice(scope_info.cleanups,
529                                       *i + 1u,
530                                       scope_info.cleanups.len()));
531             scope_clean_changed(scope_info);
532         }
533     }
534 }
535
536 pub fn block_cleanups(bcx: block) -> ~[cleanup] {
537     match *bcx.kind {
538        block_non_scope  => ~[],
539        block_scope(ref mut inf) => /*bad*/copy inf.cleanups
540     }
541 }
542
543 pub enum block_kind {
544     // A scope at the end of which temporary values created inside of it are
545     // cleaned up. May correspond to an actual block in the language, but also
546     // to an implicit scope, for example, calls introduce an implicit scope in
547     // which the arguments are evaluated and cleaned up.
548     block_scope(scope_info),
549
550     // A non-scope block is a basic block created as a translation artifact
551     // from translating code that expresses conditional logic rather than by
552     // explicit { ... } block structure in the source language.  It's called a
553     // non-scope block because it doesn't introduce a new variable scope.
554     block_non_scope,
555 }
556
557 pub struct scope_info {
558     loop_break: Option<block>,
559     loop_label: Option<ident>,
560     // A list of functions that must be run at when leaving this
561     // block, cleaning up any variables that were introduced in the
562     // block.
563     cleanups: ~[cleanup],
564     // Existing cleanup paths that may be reused, indexed by destination and
565     // cleared when the set of cleanups changes.
566     cleanup_paths: ~[cleanup_path],
567     // Unwinding landing pad. Also cleared when cleanups change.
568     landing_pad: Option<BasicBlockRef>,
569 }
570
571 pub trait get_node_info {
572     fn info(&self) -> Option<NodeInfo>;
573 }
574
575 impl get_node_info for @ast::expr {
576     fn info(&self) -> Option<NodeInfo> {
577         Some(NodeInfo { id: self.id, span: self.span })
578     }
579 }
580
581 impl get_node_info for ast::blk {
582     fn info(&self) -> Option<NodeInfo> {
583         Some(NodeInfo { id: self.node.id, span: self.span })
584     }
585 }
586
587 impl get_node_info for Option<@ast::expr> {
588     fn info(&self) -> Option<NodeInfo> {
589         self.chain_ref(|s| s.info())
590     }
591 }
592
593 pub struct NodeInfo {
594     id: ast::node_id,
595     span: span
596 }
597
598 // Basic block context.  We create a block context for each basic block
599 // (single-entry, single-exit sequence of instructions) we generate from Rust
600 // code.  Each basic block we generate is attached to a function, typically
601 // with many basic blocks per function.  All the basic blocks attached to a
602 // function are organized as a directed graph.
603 pub struct block_ {
604     // The BasicBlockRef returned from a call to
605     // llvm::LLVMAppendBasicBlock(llfn, name), which adds a basic
606     // block to the function pointed to by llfn.  We insert
607     // instructions into that block by way of this block context.
608     // The block pointing to this one in the function's digraph.
609     llbb: BasicBlockRef,
610     terminated: bool,
611     unreachable: bool,
612     parent: Option<block>,
613     // The 'kind' of basic block this is.
614     kind: @mut block_kind,
615     // Is this block part of a landing pad?
616     is_lpad: bool,
617     // info about the AST node this block originated from, if any
618     node_info: Option<NodeInfo>,
619     // The function context for the function to which this block is
620     // attached.
621     fcx: fn_ctxt
622 }
623
624 pub fn block_(llbb: BasicBlockRef, parent: Option<block>, kind: block_kind,
625               is_lpad: bool, node_info: Option<NodeInfo>, fcx: fn_ctxt)
626     -> block_ {
627
628     block_ {
629         llbb: llbb,
630         terminated: false,
631         unreachable: false,
632         parent: parent,
633         kind: @mut kind,
634         is_lpad: is_lpad,
635         node_info: node_info,
636         fcx: fcx
637     }
638 }
639
640 pub type block = @mut block_;
641
642 pub fn mk_block(llbb: BasicBlockRef, parent: Option<block>, kind: block_kind,
643             is_lpad: bool, node_info: Option<NodeInfo>, fcx: fn_ctxt)
644     -> block {
645     @mut block_(llbb, parent, kind, is_lpad, node_info, fcx)
646 }
647
648 // First two args are retptr, env
649 pub static first_real_arg: uint = 2u;
650
651 pub struct Result {
652     bcx: block,
653     val: ValueRef
654 }
655
656 pub fn rslt(bcx: block, val: ValueRef) -> Result {
657     Result {bcx: bcx, val: val}
658 }
659
660 pub impl Result {
661     fn unpack(&self, bcx: &mut block) -> ValueRef {
662         *bcx = self.bcx;
663         return self.val;
664     }
665 }
666
667 pub fn ty_str(tn: @TypeNames, t: TypeRef) -> @str {
668     return lib::llvm::type_to_str(tn, t);
669 }
670
671 pub fn val_ty(v: ValueRef) -> TypeRef {
672     unsafe {
673         return llvm::LLVMTypeOf(v);
674     }
675 }
676
677 pub fn val_str(tn: @TypeNames, v: ValueRef) -> @str {
678     return ty_str(tn, val_ty(v));
679 }
680
681 pub fn in_scope_cx(cx: block, f: &fn(si: &mut scope_info)) {
682     let mut cur = cx;
683     loop {
684         {
685             // XXX: Borrow check bug workaround.
686             let kind: &mut block_kind = &mut *cur.kind;
687             match *kind {
688               block_scope(ref mut inf) => {
689                   debug!("in_scope_cx: selected cur=%s (cx=%s)",
690                          cur.to_str(), cx.to_str());
691                   f(inf);
692                   return;
693               }
694               _ => ()
695             }
696         }
697         cur = block_parent(cur);
698     }
699 }
700
701 pub fn block_parent(cx: block) -> block {
702     match cx.parent {
703       Some(b) => b,
704       None    => cx.sess().bug(fmt!("block_parent called on root block %?",
705                                    cx))
706     }
707 }
708
709 // Accessors
710
711 pub impl block_ {
712     fn ccx(@mut self) -> @CrateContext { *self.fcx.ccx }
713     fn tcx(@mut self) -> ty::ctxt { self.fcx.ccx.tcx }
714     fn sess(@mut self) -> Session { self.fcx.ccx.sess }
715
716     fn node_id_to_str(@mut self, id: ast::node_id) -> ~str {
717         ast_map::node_id_to_str(self.tcx().items, id, self.sess().intr())
718     }
719
720     fn expr_to_str(@mut self, e: @ast::expr) -> ~str {
721         e.repr(self.tcx())
722     }
723
724     fn expr_is_lval(@mut self, e: @ast::expr) -> bool {
725         ty::expr_is_lval(self.tcx(), self.ccx().maps.method_map, e)
726     }
727
728     fn expr_kind(@mut self, e: @ast::expr) -> ty::ExprKind {
729         ty::expr_kind(self.tcx(), self.ccx().maps.method_map, e)
730     }
731
732     fn def(@mut self, nid: ast::node_id) -> ast::def {
733         match self.tcx().def_map.find(&nid) {
734             Some(&v) => v,
735             None => {
736                 self.tcx().sess.bug(fmt!(
737                     "No def associated with node id %?", nid));
738             }
739         }
740     }
741
742     fn val_str(@mut self, val: ValueRef) -> @str {
743         val_str(self.ccx().tn, val)
744     }
745
746     fn llty_str(@mut self, llty: TypeRef) -> @str {
747         ty_str(self.ccx().tn, llty)
748     }
749
750     fn ty_to_str(@mut self, t: ty::t) -> ~str {
751         t.repr(self.tcx())
752     }
753     fn to_str(@mut self) -> ~str {
754         unsafe {
755             match self.node_info {
756                 Some(node_info) => fmt!("[block %d]", node_info.id),
757                 None => fmt!("[block %x]", transmute(&*self)),
758             }
759         }
760     }
761 }
762
763 // LLVM type constructors.
764 pub fn T_void() -> TypeRef {
765     unsafe {
766         return llvm::LLVMVoidType();
767     }
768 }
769
770 pub fn T_nil() -> TypeRef {
771     return T_struct(~[], false)
772 }
773
774 pub fn T_metadata() -> TypeRef { unsafe { return llvm::LLVMMetadataType(); } }
775
776 pub fn T_i1() -> TypeRef { unsafe { return llvm::LLVMInt1Type(); } }
777
778 pub fn T_i8() -> TypeRef { unsafe { return llvm::LLVMInt8Type(); } }
779
780 pub fn T_i16() -> TypeRef { unsafe { return llvm::LLVMInt16Type(); } }
781
782 pub fn T_i32() -> TypeRef { unsafe { return llvm::LLVMInt32Type(); } }
783
784 pub fn T_i64() -> TypeRef { unsafe { return llvm::LLVMInt64Type(); } }
785
786 pub fn T_f32() -> TypeRef { unsafe { return llvm::LLVMFloatType(); } }
787
788 pub fn T_f64() -> TypeRef { unsafe { return llvm::LLVMDoubleType(); } }
789
790 pub fn T_bool() -> TypeRef { return T_i8(); }
791
792 pub fn T_int(targ_cfg: @session::config) -> TypeRef {
793     return match targ_cfg.arch {
794         X86 => T_i32(),
795         X86_64 => T_i64(),
796         Arm => T_i32(),
797         Mips => T_i32()
798     };
799 }
800
801 pub fn T_int_ty(cx: @CrateContext, t: ast::int_ty) -> TypeRef {
802     match t {
803       ast::ty_i => cx.int_type,
804       ast::ty_char => T_char(),
805       ast::ty_i8 => T_i8(),
806       ast::ty_i16 => T_i16(),
807       ast::ty_i32 => T_i32(),
808       ast::ty_i64 => T_i64()
809     }
810 }
811
812 pub fn T_uint_ty(cx: @CrateContext, t: ast::uint_ty) -> TypeRef {
813     match t {
814       ast::ty_u => cx.int_type,
815       ast::ty_u8 => T_i8(),
816       ast::ty_u16 => T_i16(),
817       ast::ty_u32 => T_i32(),
818       ast::ty_u64 => T_i64()
819     }
820 }
821
822 pub fn T_float_ty(cx: @CrateContext, t: ast::float_ty) -> TypeRef {
823     match t {
824       ast::ty_f => cx.float_type,
825       ast::ty_f32 => T_f32(),
826       ast::ty_f64 => T_f64()
827     }
828 }
829
830 pub fn T_float(targ_cfg: @session::config) -> TypeRef {
831     return match targ_cfg.arch {
832         X86 => T_f64(),
833         X86_64 => T_f64(),
834         Arm => T_f64(),
835         Mips => T_f64()
836     };
837 }
838
839 pub fn T_char() -> TypeRef { return T_i32(); }
840
841 pub fn T_size_t(targ_cfg: @session::config) -> TypeRef {
842     return T_int(targ_cfg);
843 }
844
845 pub fn T_fn(inputs: &[TypeRef], output: TypeRef) -> TypeRef {
846     unsafe {
847         return llvm::LLVMFunctionType(output, to_ptr(inputs),
848                                    inputs.len() as c_uint,
849                                    False);
850     }
851 }
852
853 pub fn T_fn_pair(cx: @CrateContext, tfn: TypeRef) -> TypeRef {
854     return T_struct(~[T_ptr(tfn), T_opaque_cbox_ptr(cx)], false);
855 }
856
857 pub fn T_ptr(t: TypeRef) -> TypeRef {
858     unsafe {
859         return llvm::LLVMPointerType(t, default_addrspace);
860     }
861 }
862
863 pub fn T_root(t: TypeRef, addrspace: addrspace) -> TypeRef {
864     unsafe {
865         return llvm::LLVMPointerType(t, addrspace);
866     }
867 }
868
869 pub fn T_struct(elts: &[TypeRef], packed: bool) -> TypeRef {
870     unsafe {
871         return llvm::LLVMStructType(to_ptr(elts),
872                                     elts.len() as c_uint,
873                                     packed as Bool);
874     }
875 }
876
877 pub fn T_named_struct(name: &str) -> TypeRef {
878     unsafe {
879         let c = llvm::LLVMGetGlobalContext();
880         return str::as_c_str(name, |buf| llvm::LLVMStructCreateNamed(c, buf));
881     }
882 }
883
884 pub fn set_struct_body(t: TypeRef, elts: &[TypeRef], packed: bool) {
885     unsafe {
886         llvm::LLVMStructSetBody(t,
887                                 to_ptr(elts),
888                                 elts.len() as c_uint,
889                                 packed as Bool);
890     }
891 }
892
893 pub fn T_empty_struct() -> TypeRef { return T_struct(~[], false); }
894
895 // A vtable is, in reality, a vtable pointer followed by zero or more pointers
896 // to tydescs and other vtables that it closes over. But the types and number
897 // of those are rarely known to the code that needs to manipulate them, so
898 // they are described by this opaque type.
899 pub fn T_vtable() -> TypeRef { T_array(T_ptr(T_i8()), 1u) }
900
901 pub fn T_task(targ_cfg: @session::config) -> TypeRef {
902     let t = T_named_struct(~"task");
903
904     // Refcount
905     // Delegate pointer
906     // Stack segment pointer
907     // Runtime SP
908     // Rust SP
909     // GC chain
910
911
912     // Domain pointer
913     // Crate cache pointer
914
915     let t_int = T_int(targ_cfg);
916     let elems =
917         ~[t_int, t_int, t_int, t_int,
918          t_int, t_int, t_int, t_int];
919     set_struct_body(t, elems, false);
920     return t;
921 }
922
923 pub fn T_tydesc_field(cx: @CrateContext, field: uint) -> TypeRef {
924     // Bit of a kludge: pick the fn typeref out of the tydesc..
925
926     unsafe {
927         let mut tydesc_elts: ~[TypeRef] =
928             vec::from_elem::<TypeRef>(abi::n_tydesc_fields,
929                                      T_nil());
930         llvm::LLVMGetStructElementTypes(
931             cx.tydesc_type,
932             ptr::to_mut_unsafe_ptr(&mut tydesc_elts[0]));
933         let t = llvm::LLVMGetElementType(tydesc_elts[field]);
934         return t;
935     }
936 }
937
938 pub fn T_generic_glue_fn(cx: @CrateContext) -> TypeRef {
939     let s = @"glue_fn";
940     match name_has_type(cx.tn, s) {
941       Some(t) => return t,
942       _ => ()
943     }
944     let t = T_tydesc_field(cx, abi::tydesc_field_drop_glue);
945     associate_type(cx.tn, s, t);
946     return t;
947 }
948
949 pub fn T_tydesc(targ_cfg: @session::config) -> TypeRef {
950     let tydesc = T_named_struct(~"tydesc");
951     let tydescpp = T_ptr(T_ptr(tydesc));
952     let pvoid = T_ptr(T_i8());
953     let glue_fn_ty =
954         T_ptr(T_fn(~[T_ptr(T_nil()), T_ptr(T_nil()), tydescpp,
955                     pvoid], T_void()));
956
957     let int_type = T_int(targ_cfg);
958     let elems =
959         ~[int_type, int_type,
960           glue_fn_ty, glue_fn_ty, glue_fn_ty, glue_fn_ty,
961           T_ptr(T_i8()), T_ptr(T_i8())];
962     set_struct_body(tydesc, elems, false);
963     return tydesc;
964 }
965
966 pub fn T_array(t: TypeRef, n: uint) -> TypeRef {
967     unsafe {
968         return llvm::LLVMArrayType(t, n as c_uint);
969     }
970 }
971
972 // Interior vector.
973 pub fn T_vec2(targ_cfg: @session::config, t: TypeRef) -> TypeRef {
974     return T_struct(~[T_int(targ_cfg), // fill
975                       T_int(targ_cfg), // alloc
976                       T_array(t, 0u)], // elements
977                     false);
978 }
979
980 pub fn T_vec(ccx: @CrateContext, t: TypeRef) -> TypeRef {
981     return T_vec2(ccx.sess.targ_cfg, t);
982 }
983
984 // Note that the size of this one is in bytes.
985 pub fn T_opaque_vec(targ_cfg: @session::config) -> TypeRef {
986     return T_vec2(targ_cfg, T_i8());
987 }
988
989 // Let T be the content of a box @T.  tuplify_box_ty(t) returns the
990 // representation of @T as a tuple (i.e., the ty::t version of what T_box()
991 // returns).
992 pub fn tuplify_box_ty(tcx: ty::ctxt, t: ty::t) -> ty::t {
993     let ptr = ty::mk_ptr(
994         tcx,
995         ty::mt {ty: ty::mk_nil(), mutbl: ast::m_imm}
996     );
997     return ty::mk_tup(tcx, ~[ty::mk_uint(), ty::mk_type(tcx),
998                          ptr, ptr,
999                          t]);
1000 }
1001
1002 pub fn T_box_header_fields(cx: @CrateContext) -> ~[TypeRef] {
1003     let ptr = T_ptr(T_i8());
1004     return ~[cx.int_type, T_ptr(cx.tydesc_type), ptr, ptr];
1005 }
1006
1007 pub fn T_box_header(cx: @CrateContext) -> TypeRef {
1008     return T_struct(T_box_header_fields(cx), false);
1009 }
1010
1011 pub fn T_box(cx: @CrateContext, t: TypeRef) -> TypeRef {
1012     return T_struct(vec::append(T_box_header_fields(cx), ~[t]), false);
1013 }
1014
1015 pub fn T_box_ptr(t: TypeRef) -> TypeRef {
1016     unsafe {
1017         return llvm::LLVMPointerType(t, gc_box_addrspace);
1018     }
1019 }
1020
1021 pub fn T_opaque_box(cx: @CrateContext) -> TypeRef {
1022     return T_box(cx, T_i8());
1023 }
1024
1025 pub fn T_opaque_box_ptr(cx: @CrateContext) -> TypeRef {
1026     return T_box_ptr(T_opaque_box(cx));
1027 }
1028
1029 pub fn T_unique(cx: @CrateContext, t: TypeRef) -> TypeRef {
1030     return T_struct(vec::append(T_box_header_fields(cx), ~[t]), false);
1031 }
1032
1033 pub fn T_unique_ptr(t: TypeRef) -> TypeRef {
1034     unsafe {
1035         return llvm::LLVMPointerType(t, gc_box_addrspace);
1036     }
1037 }
1038
1039 pub fn T_port(cx: @CrateContext, _t: TypeRef) -> TypeRef {
1040     return T_struct(~[cx.int_type], false); // Refcount
1041
1042 }
1043
1044 pub fn T_chan(cx: @CrateContext, _t: TypeRef) -> TypeRef {
1045     return T_struct(~[cx.int_type], false); // Refcount
1046
1047 }
1048
1049 pub fn T_taskptr(cx: @CrateContext) -> TypeRef { return T_ptr(cx.task_type); }
1050
1051
1052 pub fn T_opaque_cbox_ptr(cx: @CrateContext) -> TypeRef {
1053     // closures look like boxes (even when they are ~fn or &fn)
1054     // see trans_closure.rs
1055     return T_opaque_box_ptr(cx);
1056 }
1057
1058 pub fn T_enum_discrim(cx: @CrateContext) -> TypeRef {
1059     return cx.int_type;
1060 }
1061
1062 pub fn T_captured_tydescs(cx: @CrateContext, n: uint) -> TypeRef {
1063     return T_struct(vec::from_elem::<TypeRef>(n, T_ptr(cx.tydesc_type)), false);
1064 }
1065
1066 pub fn T_opaque_trait(cx: @CrateContext, store: ty::TraitStore) -> TypeRef {
1067     match store {
1068         ty::BoxTraitStore => {
1069             T_struct(~[T_ptr(cx.tydesc_type), T_opaque_box_ptr(cx)], false)
1070         }
1071         ty::UniqTraitStore => {
1072             T_struct(~[T_ptr(cx.tydesc_type),
1073                        T_unique_ptr(T_unique(cx, T_i8())),
1074                        T_ptr(cx.tydesc_type)],
1075                      false)
1076         }
1077         ty::RegionTraitStore(_) => {
1078             T_struct(~[T_ptr(cx.tydesc_type), T_ptr(T_i8())], false)
1079         }
1080     }
1081 }
1082
1083 pub fn T_opaque_port_ptr() -> TypeRef { return T_ptr(T_i8()); }
1084
1085 pub fn T_opaque_chan_ptr() -> TypeRef { return T_ptr(T_i8()); }
1086
1087
1088 // LLVM constant constructors.
1089 pub fn C_null(t: TypeRef) -> ValueRef {
1090     unsafe {
1091         return llvm::LLVMConstNull(t);
1092     }
1093 }
1094
1095 pub fn C_undef(t: TypeRef) -> ValueRef {
1096     unsafe {
1097         return llvm::LLVMGetUndef(t);
1098     }
1099 }
1100
1101 pub fn C_integral(t: TypeRef, u: u64, sign_extend: Bool) -> ValueRef {
1102     unsafe {
1103         return llvm::LLVMConstInt(t, u, sign_extend);
1104     }
1105 }
1106
1107 pub fn C_floating(s: &str, t: TypeRef) -> ValueRef {
1108     unsafe {
1109         return str::as_c_str(s, |buf| llvm::LLVMConstRealOfString(t, buf));
1110     }
1111 }
1112
1113 pub fn C_nil() -> ValueRef {
1114     return C_struct(~[]);
1115 }
1116
1117 pub fn C_bool(b: bool) -> ValueRef {
1118     C_integral(T_bool(), if b { 1u64 } else { 0u64 }, False)
1119 }
1120
1121 pub fn C_i1(b: bool) -> ValueRef {
1122     return C_integral(T_i1(), if b { 1 } else { 0 }, False);
1123 }
1124
1125 pub fn C_i32(i: i32) -> ValueRef {
1126     return C_integral(T_i32(), i as u64, True);
1127 }
1128
1129 pub fn C_i64(i: i64) -> ValueRef {
1130     return C_integral(T_i64(), i as u64, True);
1131 }
1132
1133 pub fn C_int(cx: @CrateContext, i: int) -> ValueRef {
1134     return C_integral(cx.int_type, i as u64, True);
1135 }
1136
1137 pub fn C_uint(cx: @CrateContext, i: uint) -> ValueRef {
1138     return C_integral(cx.int_type, i as u64, False);
1139 }
1140
1141 pub fn C_u8(i: uint) -> ValueRef {
1142     return C_integral(T_i8(), i as u64, False);
1143 }
1144
1145
1146 // This is a 'c-like' raw string, which differs from
1147 // our boxed-and-length-annotated strings.
1148 pub fn C_cstr(cx: @CrateContext, s: @~str) -> ValueRef {
1149     unsafe {
1150         match cx.const_cstr_cache.find(&s) {
1151             Some(&llval) => return llval,
1152             None => ()
1153         }
1154
1155         let sc = do str::as_c_str(*s) |buf| {
1156             llvm::LLVMConstString(buf, s.len() as c_uint, False)
1157         };
1158         let g =
1159             str::as_c_str(fmt!("str%u", (cx.names)(~"str").repr),
1160                         |buf| llvm::LLVMAddGlobal(cx.llmod, val_ty(sc), buf));
1161         llvm::LLVMSetInitializer(g, sc);
1162         llvm::LLVMSetGlobalConstant(g, True);
1163         lib::llvm::SetLinkage(g, lib::llvm::InternalLinkage);
1164
1165         cx.const_cstr_cache.insert(s, g);
1166
1167         return g;
1168     }
1169 }
1170
1171 // NB: Do not use `do_spill_noroot` to make this into a constant string, or
1172 // you will be kicked off fast isel. See issue #4352 for an example of this.
1173 pub fn C_estr_slice(cx: @CrateContext, s: @~str) -> ValueRef {
1174     unsafe {
1175         let len = s.len();
1176         let cs = llvm::LLVMConstPointerCast(C_cstr(cx, s), T_ptr(T_i8()));
1177         C_struct(~[cs, C_uint(cx, len + 1u /* +1 for null */)])
1178     }
1179 }
1180
1181 // Returns a Plain Old LLVM String:
1182 pub fn C_postr(s: &str) -> ValueRef {
1183     unsafe {
1184         return do str::as_c_str(s) |buf| {
1185             llvm::LLVMConstString(buf, str::len(s) as c_uint, False)
1186         };
1187     }
1188 }
1189
1190 pub fn C_zero_byte_arr(size: uint) -> ValueRef {
1191     unsafe {
1192         let mut i = 0u;
1193         let mut elts: ~[ValueRef] = ~[];
1194         while i < size { elts.push(C_u8(0u)); i += 1u; }
1195         return llvm::LLVMConstArray(T_i8(),
1196                                     vec::raw::to_ptr(elts),
1197                                     elts.len() as c_uint);
1198     }
1199 }
1200
1201 pub fn C_struct(elts: &[ValueRef]) -> ValueRef {
1202     unsafe {
1203         do vec::as_imm_buf(elts) |ptr, len| {
1204             llvm::LLVMConstStruct(ptr, len as c_uint, False)
1205         }
1206     }
1207 }
1208
1209 pub fn C_packed_struct(elts: &[ValueRef]) -> ValueRef {
1210     unsafe {
1211         do vec::as_imm_buf(elts) |ptr, len| {
1212             llvm::LLVMConstStruct(ptr, len as c_uint, True)
1213         }
1214     }
1215 }
1216
1217 pub fn C_named_struct(T: TypeRef, elts: &[ValueRef]) -> ValueRef {
1218     unsafe {
1219         do vec::as_imm_buf(elts) |ptr, len| {
1220             llvm::LLVMConstNamedStruct(T, ptr, len as c_uint)
1221         }
1222     }
1223 }
1224
1225 pub fn C_array(ty: TypeRef, elts: &[ValueRef]) -> ValueRef {
1226     unsafe {
1227         return llvm::LLVMConstArray(ty, vec::raw::to_ptr(elts),
1228                                  elts.len() as c_uint);
1229     }
1230 }
1231
1232 pub fn C_bytes(bytes: &[u8]) -> ValueRef {
1233     unsafe {
1234         return llvm::LLVMConstString(
1235             cast::transmute(vec::raw::to_ptr(bytes)),
1236             bytes.len() as c_uint, True);
1237     }
1238 }
1239
1240 pub fn C_bytes_plus_null(bytes: &[u8]) -> ValueRef {
1241     unsafe {
1242         return llvm::LLVMConstString(
1243             cast::transmute(vec::raw::to_ptr(bytes)),
1244             bytes.len() as c_uint, False);
1245     }
1246 }
1247
1248 pub fn C_shape(ccx: @CrateContext, bytes: ~[u8]) -> ValueRef {
1249     unsafe {
1250         let llshape = C_bytes_plus_null(bytes);
1251         let name = fmt!("shape%u", (ccx.names)(~"shape").repr);
1252         let llglobal = str::as_c_str(name, |buf| {
1253             llvm::LLVMAddGlobal(ccx.llmod, val_ty(llshape), buf)
1254         });
1255         llvm::LLVMSetInitializer(llglobal, llshape);
1256         llvm::LLVMSetGlobalConstant(llglobal, True);
1257         lib::llvm::SetLinkage(llglobal, lib::llvm::InternalLinkage);
1258         return llvm::LLVMConstPointerCast(llglobal, T_ptr(T_i8()));
1259     }
1260 }
1261
1262 pub fn get_param(fndecl: ValueRef, param: uint) -> ValueRef {
1263     unsafe {
1264         llvm::LLVMGetParam(fndecl, param as c_uint)
1265     }
1266 }
1267
1268 pub fn const_get_elt(cx: @CrateContext, v: ValueRef, us: &[c_uint])
1269                   -> ValueRef {
1270     unsafe {
1271         let r = do vec::as_imm_buf(us) |p, len| {
1272             llvm::LLVMConstExtractValue(v, p, len as c_uint)
1273         };
1274
1275         debug!("const_get_elt(v=%s, us=%?, r=%s)",
1276                val_str(cx.tn, v), us, val_str(cx.tn, r));
1277
1278         return r;
1279     }
1280 }
1281
1282 pub fn const_to_int(v: ValueRef) -> c_longlong {
1283     unsafe {
1284         llvm::LLVMConstIntGetSExtValue(v)
1285     }
1286 }
1287
1288 pub fn const_to_uint(v: ValueRef) -> c_ulonglong {
1289     unsafe {
1290         llvm::LLVMConstIntGetZExtValue(v)
1291     }
1292 }
1293
1294 pub fn is_undef(val: ValueRef) -> bool {
1295     unsafe {
1296         llvm::LLVMIsUndef(val) != False
1297     }
1298 }
1299
1300 pub fn is_null(val: ValueRef) -> bool {
1301     unsafe {
1302         llvm::LLVMIsNull(val) != False
1303     }
1304 }
1305
1306 // Used to identify cached monomorphized functions and vtables
1307 #[deriving(Eq)]
1308 pub enum mono_param_id {
1309     mono_precise(ty::t, Option<~[mono_id]>),
1310     mono_any,
1311     mono_repr(uint /* size */,
1312               uint /* align */,
1313               MonoDataClass,
1314               datum::DatumMode),
1315 }
1316
1317 #[deriving(Eq)]
1318 pub enum MonoDataClass {
1319     MonoBits,    // Anything not treated differently from arbitrary integer data
1320     MonoNonNull, // Non-null pointers (used for optional-pointer optimization)
1321     // FIXME(#3547)---scalars and floats are
1322     // treated differently in most ABIs.  But we
1323     // should be doing something more detailed
1324     // here.
1325     MonoFloat
1326 }
1327
1328 pub fn mono_data_classify(t: ty::t) -> MonoDataClass {
1329     match ty::get(t).sty {
1330         ty::ty_float(_) => MonoFloat,
1331         ty::ty_rptr(*) | ty::ty_uniq(*) |
1332         ty::ty_box(*) | ty::ty_opaque_box(*) |
1333         ty::ty_estr(ty::vstore_uniq) | ty::ty_evec(_, ty::vstore_uniq) |
1334         ty::ty_estr(ty::vstore_box) | ty::ty_evec(_, ty::vstore_box) |
1335         ty::ty_bare_fn(*) => MonoNonNull,
1336         // Is that everything?  Would closures or slices qualify?
1337         _ => MonoBits
1338     }
1339 }
1340
1341
1342 #[deriving(Eq)]
1343 pub struct mono_id_ {
1344     def: ast::def_id,
1345     params: ~[mono_param_id],
1346     impl_did_opt: Option<ast::def_id>
1347 }
1348
1349 pub type mono_id = @mono_id_;
1350
1351 impl to_bytes::IterBytes for mono_param_id {
1352     fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
1353         match *self {
1354             mono_precise(t, ref mids) =>
1355                 to_bytes::iter_bytes_3(&0u8, &ty::type_id(t), mids, lsb0, f),
1356
1357             mono_any => 1u8.iter_bytes(lsb0, f),
1358
1359             mono_repr(ref a, ref b, ref c, ref d) =>
1360                 to_bytes::iter_bytes_5(&2u8, a, b, c, d, lsb0, f)
1361         }
1362     }
1363 }
1364
1365 impl to_bytes::IterBytes for MonoDataClass {
1366     fn iter_bytes(&self, lsb0: bool, f:to_bytes::Cb) {
1367         (*self as u8).iter_bytes(lsb0, f)
1368     }
1369 }
1370
1371 impl to_bytes::IterBytes for mono_id_ {
1372     fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
1373         to_bytes::iter_bytes_2(&self.def, &self.params, lsb0, f);
1374     }
1375 }
1376
1377 pub fn umax(cx: block, a: ValueRef, b: ValueRef) -> ValueRef {
1378     let cond = build::ICmp(cx, lib::llvm::IntULT, a, b);
1379     return build::Select(cx, cond, b, a);
1380 }
1381
1382 pub fn umin(cx: block, a: ValueRef, b: ValueRef) -> ValueRef {
1383     let cond = build::ICmp(cx, lib::llvm::IntULT, a, b);
1384     return build::Select(cx, cond, a, b);
1385 }
1386
1387 pub fn align_to(cx: block, off: ValueRef, align: ValueRef) -> ValueRef {
1388     let mask = build::Sub(cx, align, C_int(cx.ccx(), 1));
1389     let bumped = build::Add(cx, off, mask);
1390     return build::And(cx, bumped, build::Not(cx, mask));
1391 }
1392
1393 pub fn path_str(sess: session::Session, p: &[path_elt]) -> ~str {
1394     let mut r = ~"", first = true;
1395     for p.each |e| {
1396         match *e {
1397             ast_map::path_name(s) | ast_map::path_mod(s) => {
1398                 if first { first = false; }
1399                 else { r += ~"::"; }
1400                 r += *sess.str_of(s);
1401             }
1402         }
1403     }
1404     r
1405 }
1406
1407 pub fn monomorphize_type(bcx: block, t: ty::t) -> ty::t {
1408     match bcx.fcx.param_substs {
1409         Some(substs) => {
1410             ty::subst_tps(bcx.tcx(), substs.tys, substs.self_ty, t)
1411         }
1412         _ => { assert!(!ty::type_has_params(t)); t }
1413     }
1414 }
1415
1416 pub fn node_id_type(bcx: block, id: ast::node_id) -> ty::t {
1417     let tcx = bcx.tcx();
1418     let t = ty::node_id_to_type(tcx, id);
1419     monomorphize_type(bcx, t)
1420 }
1421
1422 pub fn expr_ty(bcx: block, ex: @ast::expr) -> ty::t {
1423     node_id_type(bcx, ex.id)
1424 }
1425
1426 pub fn expr_ty_adjusted(bcx: block, ex: @ast::expr) -> ty::t {
1427     let tcx = bcx.tcx();
1428     let t = ty::expr_ty_adjusted(tcx, ex);
1429     monomorphize_type(bcx, t)
1430 }
1431
1432 pub fn node_id_type_params(bcx: block, id: ast::node_id) -> ~[ty::t] {
1433     let tcx = bcx.tcx();
1434     let params = ty::node_id_to_type_params(tcx, id);
1435
1436     if !params.all(|t| !ty::type_needs_infer(*t)) {
1437         bcx.sess().bug(
1438             fmt!("Type parameters for node %d include inference types: %s",
1439                  id, str::connect(params.map(|t| bcx.ty_to_str(*t)), ",")));
1440     }
1441
1442     match bcx.fcx.param_substs {
1443       Some(substs) => {
1444         do vec::map(params) |t| {
1445             ty::subst_tps(tcx, substs.tys, substs.self_ty, *t)
1446         }
1447       }
1448       _ => params
1449     }
1450 }
1451
1452 pub fn node_vtables(bcx: block, id: ast::node_id)
1453                  -> Option<typeck::vtable_res> {
1454     let raw_vtables = bcx.ccx().maps.vtable_map.find(&id);
1455     raw_vtables.map(
1456         |&vts| resolve_vtables_in_fn_ctxt(bcx.fcx, *vts))
1457 }
1458
1459 pub fn resolve_vtables_in_fn_ctxt(fcx: fn_ctxt, vts: typeck::vtable_res)
1460     -> typeck::vtable_res {
1461     @vec::map(*vts, |d| resolve_vtable_in_fn_ctxt(fcx, copy *d))
1462 }
1463
1464 // Apply the typaram substitutions in the fn_ctxt to a vtable. This should
1465 // eliminate any vtable_params.
1466 pub fn resolve_vtable_in_fn_ctxt(fcx: fn_ctxt, vt: typeck::vtable_origin)
1467     -> typeck::vtable_origin {
1468     let tcx = fcx.ccx.tcx;
1469     match vt {
1470         typeck::vtable_static(trait_id, tys, sub) => {
1471             let tys = match fcx.param_substs {
1472                 Some(substs) => {
1473                     do vec::map(tys) |t| {
1474                         ty::subst_tps(tcx, substs.tys, substs.self_ty, *t)
1475                     }
1476                 }
1477                 _ => tys
1478             };
1479             typeck::vtable_static(trait_id, tys,
1480                                   resolve_vtables_in_fn_ctxt(fcx, sub))
1481         }
1482         typeck::vtable_param(n_param, n_bound) => {
1483             match fcx.param_substs {
1484                 Some(substs) => {
1485                     find_vtable(tcx, substs, n_param, n_bound)
1486                 }
1487                 _ => {
1488                     tcx.sess.bug(fmt!(
1489                         "resolve_vtable_in_fn_ctxt: asked to lookup but \
1490                          no vtables in the fn_ctxt!"))
1491                 }
1492             }
1493         }
1494     }
1495 }
1496
1497 pub fn find_vtable(tcx: ty::ctxt, ps: &param_substs,
1498                    n_param: uint, n_bound: uint)
1499     -> typeck::vtable_origin {
1500     debug!("find_vtable(n_param=%u, n_bound=%u, ps=%s)",
1501            n_param, n_bound, ps.repr(tcx));
1502
1503     // Vtables are stored in a flat array, finding the right one is
1504     // somewhat awkward
1505     let first_n_type_param_defs = ps.type_param_defs.slice(0, n_param);
1506     let vtables_to_skip =
1507         ty::count_traits_and_supertraits(tcx, first_n_type_param_defs);
1508     let vtable_off = vtables_to_skip + n_bound;
1509     /*bad*/ copy ps.vtables.get()[vtable_off]
1510 }
1511
1512 pub fn dummy_substs(tps: ~[ty::t]) -> ty::substs {
1513     substs {
1514         self_r: Some(ty::re_bound(ty::br_self)),
1515         self_ty: None,
1516         tps: tps
1517     }
1518 }
1519
1520 // Casts a Rust bool value to an i1.
1521 pub fn bool_to_i1(bcx: block, llval: ValueRef) -> ValueRef {
1522     build::ICmp(bcx, lib::llvm::IntNE, llval, C_bool(false))
1523 }
1524
1525 //
1526 // Local Variables:
1527 // mode: rust
1528 // fill-column: 78;
1529 // indent-tabs-mode: nil
1530 // c-basic-offset: 4
1531 // buffer-file-coding-system: utf-8-unix
1532 // End:
1533 //