]> git.lizzy.rs Git - rust.git/blob - src/librustc/middle/trans/base.rs
a8b0da47e9ac2344c48571ab47a99fe0b56fdf71
[rust.git] / src / librustc / middle / trans / base.rs
1 // Copyright 2012 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 // trans.rs: Translate the completed AST to the LLVM IR.
12 //
13 // Some functions here, such as trans_block and trans_expr, return a value --
14 // the result of the translation to LLVM -- while others, such as trans_fn,
15 // trans_impl, and trans_item, are called only for the side effect of adding a
16 // particular definition to the LLVM IR output we're producing.
17 //
18 // Hopefully useful general knowledge about trans:
19 //
20 //   * There's no way to find out the ty::t type of a ValueRef.  Doing so
21 //     would be "trying to get the eggs out of an omelette" (credit:
22 //     pcwalton).  You can, instead, find out its TypeRef by calling val_ty,
23 //     but many TypeRefs correspond to one ty::t; for instance, tup(int, int,
24 //     int) and rec(x=int, y=int, z=int) will have the same TypeRef.
25
26 use core::prelude::*;
27
28 use back::link::{mangle_exported_name};
29 use back::link::{mangle_internal_name_by_path_and_seq};
30 use back::link::{mangle_internal_name_by_path};
31 use back::link::{mangle_internal_name_by_seq};
32 use back::link::{mangle_internal_name_by_type_only};
33 use back::{link, abi, upcall};
34 use driver::session;
35 use driver::session::Session;
36 use lib::llvm::{ModuleRef, ValueRef, TypeRef, BasicBlockRef};
37 use lib::llvm::{True, False};
38 use lib::llvm::{llvm, mk_target_data, mk_type_names};
39 use lib;
40 use metadata::common::link_meta;
41 use metadata::{csearch, cstore, decoder, encoder};
42 use middle::astencode;
43 use middle::pat_util::*;
44 use middle::resolve;
45 use middle::trans::_match;
46 use middle::trans::build::*;
47 use middle::trans::callee;
48 use middle::trans::common::*;
49 use middle::trans::consts;
50 use middle::trans::controlflow;
51 use middle::trans::datum;
52 use middle::trans::debuginfo;
53 use middle::trans::expr;
54 use middle::trans::foreign;
55 use middle::trans::glue;
56 use middle::trans::inline;
57 use middle::trans::meth;
58 use middle::trans::monomorphize;
59 use middle::trans::reachable;
60 use middle::trans::shape::*;
61 use middle::trans::tvec;
62 use middle::trans::type_of::*;
63 use util::common::indenter;
64 use util::common::is_main_name;
65 use util::ppaux::{ty_to_str, ty_to_short_str};
66 use util::ppaux;
67
68 use core::either;
69 use core::hash;
70 use core::int;
71 use core::io;
72 use core::libc::{c_uint, c_ulonglong};
73 use core::option::{is_none, is_some};
74 use core::option;
75 use core::uint;
76 use std::map::HashMap;
77 use std::smallintmap;
78 use std::{map, time, list};
79 use syntax::ast_map::{path, path_elt_to_str, path_mod, path_name};
80 use syntax::ast_util::{def_id_of_def, local_def, path_to_ident};
81 use syntax::attr;
82 use syntax::codemap::span;
83 use syntax::diagnostic::expect;
84 use syntax::parse::token::special_idents;
85 use syntax::print::pprust::{expr_to_str, stmt_to_str, path_to_str};
86 use syntax::visit;
87 use syntax::visit::vt;
88 use syntax::{ast, ast_util, codemap, ast_map};
89
90 struct icx_popper {
91     ccx: @crate_ctxt,
92     drop {
93       if self.ccx.sess.count_llvm_insns() {
94           self.ccx.stats.llvm_insn_ctxt.pop();
95       }
96     }
97 }
98
99 fn icx_popper(ccx: @crate_ctxt) -> icx_popper {
100     icx_popper {
101         ccx: ccx
102     }
103 }
104
105 trait get_insn_ctxt {
106     fn insn_ctxt(s: &str) -> icx_popper;
107 }
108
109 impl @crate_ctxt: get_insn_ctxt {
110     fn insn_ctxt(s: &str) -> icx_popper {
111         debug!("new insn_ctxt: %s", s);
112         if self.sess.count_llvm_insns() {
113             self.stats.llvm_insn_ctxt.push(str::from_slice(s));
114         }
115         icx_popper(self)
116     }
117 }
118
119 impl block: get_insn_ctxt {
120     fn insn_ctxt(s: &str) -> icx_popper {
121         self.ccx().insn_ctxt(s)
122     }
123 }
124
125 impl fn_ctxt: get_insn_ctxt {
126     fn insn_ctxt(s: &str) -> icx_popper {
127         self.ccx.insn_ctxt(s)
128     }
129 }
130
131 fn log_fn_time(ccx: @crate_ctxt, +name: ~str, start: time::Timespec,
132                end: time::Timespec) {
133     let elapsed = 1000 * ((end.sec - start.sec) as int) +
134         ((end.nsec as int) - (start.nsec as int)) / 1000000;
135     ccx.stats.fn_times.push({ident: name, time: elapsed});
136 }
137
138 fn decl_fn(llmod: ModuleRef, name: ~str, cc: lib::llvm::CallConv,
139            llty: TypeRef) -> ValueRef {
140     let llfn: ValueRef = str::as_c_str(name, |buf| {
141         unsafe {
142             llvm::LLVMGetOrInsertFunction(llmod, buf, llty)
143         }
144     });
145     unsafe {
146         lib::llvm::SetFunctionCallConv(llfn, cc);
147     }
148     return llfn;
149 }
150
151 fn decl_cdecl_fn(llmod: ModuleRef, +name: ~str, llty: TypeRef) -> ValueRef {
152     return decl_fn(llmod, name, lib::llvm::CCallConv, llty);
153 }
154
155 // Only use this if you are going to actually define the function. It's
156 // not valid to simply declare a function as internal.
157 fn decl_internal_cdecl_fn(llmod: ModuleRef, +name: ~str, llty: TypeRef) ->
158    ValueRef {
159     let llfn = decl_cdecl_fn(llmod, name, llty);
160     lib::llvm::SetLinkage(llfn, lib::llvm::InternalLinkage);
161     return llfn;
162 }
163
164 fn get_extern_fn(externs: HashMap<~str, ValueRef>,
165                  llmod: ModuleRef,
166                  +name: ~str,
167                  cc: lib::llvm::CallConv,
168                  ty: TypeRef) -> ValueRef {
169     // XXX: Bad copy.
170     if externs.contains_key(copy name) { return externs.get(name); }
171     // XXX: Bad copy.
172     let f = decl_fn(llmod, copy name, cc, ty);
173     externs.insert(name, f);
174     return f;
175 }
176
177 fn get_extern_const(externs: HashMap<~str, ValueRef>, llmod: ModuleRef,
178                     +name: ~str, ty: TypeRef) -> ValueRef {
179     unsafe {
180         // XXX: Bad copy.
181         if externs.contains_key(copy name) { return externs.get(name); }
182         let c = str::as_c_str(name, |buf| {
183             llvm::LLVMAddGlobal(llmod, ty, buf)
184         });
185         externs.insert(name, c);
186         return c;
187     }
188 }
189
190 fn get_simple_extern_fn(cx: block,
191                         externs: HashMap<~str, ValueRef>,
192                         llmod: ModuleRef,
193                         +name: ~str,
194                         n_args: int) -> ValueRef {
195     let _icx = cx.insn_ctxt("get_simple_extern_fn");
196     let ccx = cx.fcx.ccx;
197     let inputs = vec::from_elem(n_args as uint, ccx.int_type);
198     let output = ccx.int_type;
199     let t = T_fn(inputs, output);
200     return get_extern_fn(externs, llmod, name, lib::llvm::CCallConv, t);
201 }
202
203 fn trans_foreign_call(cx: block, externs: HashMap<~str, ValueRef>,
204                       llmod: ModuleRef, +name: ~str, args: ~[ValueRef]) ->
205    ValueRef {
206     let _icx = cx.insn_ctxt("trans_foreign_call");
207     let n = args.len() as int;
208     let llforeign: ValueRef =
209         get_simple_extern_fn(cx, externs, llmod, name, n);
210     return Call(cx, llforeign, args);
211 }
212
213 fn umax(cx: block, a: ValueRef, b: ValueRef) -> ValueRef {
214     let _icx = cx.insn_ctxt("umax");
215     let cond = ICmp(cx, lib::llvm::IntULT, a, b);
216     return Select(cx, cond, b, a);
217 }
218
219 fn umin(cx: block, a: ValueRef, b: ValueRef) -> ValueRef {
220     let _icx = cx.insn_ctxt("umin");
221     let cond = ICmp(cx, lib::llvm::IntULT, a, b);
222     return Select(cx, cond, a, b);
223 }
224
225 // Given a pointer p, returns a pointer sz(p) (i.e., inc'd by sz bytes).
226 // The type of the returned pointer is always i8*.  If you care about the
227 // return type, use bump_ptr().
228 fn ptr_offs(bcx: block, base: ValueRef, sz: ValueRef) -> ValueRef {
229     let _icx = bcx.insn_ctxt("ptr_offs");
230     let raw = PointerCast(bcx, base, T_ptr(T_i8()));
231     InBoundsGEP(bcx, raw, ~[sz])
232 }
233
234 // Increment a pointer by a given amount and then cast it to be a pointer
235 // to a given type.
236 fn bump_ptr(bcx: block, t: ty::t, base: ValueRef, sz: ValueRef) ->
237    ValueRef {
238     let _icx = bcx.insn_ctxt("bump_ptr");
239     let ccx = bcx.ccx();
240     let bumped = ptr_offs(bcx, base, sz);
241     let typ = T_ptr(type_of(ccx, t));
242     PointerCast(bcx, bumped, typ)
243 }
244
245 // Replacement for the LLVM 'GEP' instruction when field indexing into a enum.
246 // @llblobptr is the data part of a enum value; its actual type
247 // is meaningless, as it will be cast away.
248 fn GEP_enum(bcx: block, llblobptr: ValueRef, enum_id: ast::def_id,
249             variant_id: ast::def_id, ty_substs: ~[ty::t],
250             ix: uint) -> ValueRef {
251     let _icx = bcx.insn_ctxt("GEP_enum");
252     let ccx = bcx.ccx();
253     let variant = ty::enum_variant_with_id(ccx.tcx, enum_id, variant_id);
254     assert ix < variant.args.len();
255
256     let arg_lltys = vec::map(variant.args, |aty| {
257         type_of(ccx, ty::subst_tps(ccx.tcx, ty_substs, None, *aty))
258     });
259     let typed_blobptr = PointerCast(bcx, llblobptr,
260                                     T_ptr(T_struct(arg_lltys)));
261     GEPi(bcx, typed_blobptr, [0u, ix])
262 }
263
264 // Returns a pointer to the body for the box. The box may be an opaque
265 // box. The result will be casted to the type of body_t, if it is statically
266 // known.
267 //
268 // The runtime equivalent is box_body() in "rust_internal.h".
269 fn opaque_box_body(bcx: block,
270                    body_t: ty::t,
271                    boxptr: ValueRef) -> ValueRef {
272     let _icx = bcx.insn_ctxt("opaque_box_body");
273     let ccx = bcx.ccx();
274     let boxptr = PointerCast(bcx, boxptr, T_ptr(T_box_header(ccx)));
275     let bodyptr = GEPi(bcx, boxptr, [1u]);
276     PointerCast(bcx, bodyptr, T_ptr(type_of(ccx, body_t)))
277 }
278
279 // malloc_raw_dyn: allocates a box to contain a given type, but with a
280 // potentially dynamic size.
281 fn malloc_raw_dyn(bcx: block,
282                   t: ty::t,
283                   heap: heap,
284                   size: ValueRef) -> Result {
285     let _icx = bcx.insn_ctxt("malloc_raw");
286     let ccx = bcx.ccx();
287
288     let (mk_fn, langcall) = match heap {
289         heap_shared => {
290             (ty::mk_imm_box, bcx.tcx().lang_items.malloc_fn())
291         }
292         heap_exchange => {
293             (ty::mk_imm_uniq, bcx.tcx().lang_items.exchange_malloc_fn())
294         }
295     };
296
297     // Grab the TypeRef type of box_ptr_ty.
298     let box_ptr_ty = mk_fn(bcx.tcx(), t);
299     let llty = type_of(ccx, box_ptr_ty);
300
301     // Get the tydesc for the body:
302     let static_ti = get_tydesc(ccx, t);
303     glue::lazily_emit_all_tydesc_glue(ccx, static_ti);
304
305     // Allocate space:
306     let tydesc = PointerCast(bcx, static_ti.tydesc, T_ptr(T_i8()));
307     let rval = alloca_zeroed(bcx, T_ptr(T_i8()));
308     let bcx = callee::trans_rtcall_or_lang_call(
309         bcx,
310         langcall,
311         ~[tydesc, size],
312         expr::SaveIn(rval));
313     return rslt(bcx, PointerCast(bcx, Load(bcx, rval), llty));
314 }
315
316 /**
317 * Get the type of a box in the default address space.
318 *
319 * Shared box pointers live in address space 1 so the GC strategy can find
320 * them. Before taking a pointer to the inside of a box it should be cast into
321 * address space 0. Otherwise the resulting (non-box) pointer will be in the
322 * wrong address space and thus be the wrong type.
323 */
324 fn non_gc_box_cast(bcx: block, val: ValueRef) -> ValueRef {
325     unsafe {
326         debug!("non_gc_box_cast");
327         add_comment(bcx, ~"non_gc_box_cast");
328         assert(llvm::LLVMGetPointerAddressSpace(val_ty(val)) ==
329                 gc_box_addrspace || bcx.unreachable);
330         let non_gc_t = T_ptr(llvm::LLVMGetElementType(val_ty(val)));
331         PointerCast(bcx, val, non_gc_t)
332     }
333 }
334
335 // malloc_raw: expects an unboxed type and returns a pointer to
336 // enough space for a box of that type.  This includes a rust_opaque_box
337 // header.
338 fn malloc_raw(bcx: block, t: ty::t, heap: heap) -> Result {
339     malloc_raw_dyn(bcx, t, heap, llsize_of(bcx.ccx(), type_of(bcx.ccx(), t)))
340 }
341
342 // malloc_general_dyn: usefully wraps malloc_raw_dyn; allocates a box,
343 // and pulls out the body
344 fn malloc_general_dyn(bcx: block, t: ty::t, heap: heap, size: ValueRef)
345     -> {bcx: block, box: ValueRef, body: ValueRef} {
346     let _icx = bcx.insn_ctxt("malloc_general");
347     let Result {bcx: bcx, val: llbox} = malloc_raw_dyn(bcx, t, heap, size);
348     let non_gc_box = non_gc_box_cast(bcx, llbox);
349     let body = GEPi(bcx, non_gc_box, [0u, abi::box_field_body]);
350     return {bcx: bcx, box: llbox, body: body};
351 }
352
353 fn malloc_general(bcx: block, t: ty::t, heap: heap)
354     -> {bcx: block, box: ValueRef, body: ValueRef} {
355     malloc_general_dyn(bcx, t, heap,
356                        llsize_of(bcx.ccx(), type_of(bcx.ccx(), t)))
357 }
358 fn malloc_boxed(bcx: block, t: ty::t)
359     -> {bcx: block, box: ValueRef, body: ValueRef} {
360     malloc_general(bcx, t, heap_shared)
361 }
362 fn malloc_unique(bcx: block, t: ty::t)
363     -> {bcx: block, box: ValueRef, body: ValueRef} {
364     malloc_general(bcx, t, heap_exchange)
365 }
366
367 // Type descriptor and type glue stuff
368
369 fn get_tydesc_simple(ccx: @crate_ctxt, t: ty::t) -> ValueRef {
370     get_tydesc(ccx, t).tydesc
371 }
372
373 fn get_tydesc(ccx: @crate_ctxt, t: ty::t) -> @tydesc_info {
374     match ccx.tydescs.find(t) {
375       Some(inf) => inf,
376       _ => {
377         ccx.stats.n_static_tydescs += 1u;
378         let inf = glue::declare_tydesc(ccx, t);
379         ccx.tydescs.insert(t, inf);
380         inf
381       }
382     }
383 }
384
385 fn set_no_inline(f: ValueRef) {
386     unsafe {
387         llvm::LLVMAddFunctionAttr(f,
388                                   lib::llvm::NoInlineAttribute as c_ulonglong,
389                                   0u as c_ulonglong);
390     }
391 }
392
393 fn set_no_unwind(f: ValueRef) {
394     unsafe {
395         llvm::LLVMAddFunctionAttr(f,
396                                   lib::llvm::NoUnwindAttribute as c_ulonglong,
397                                   0u as c_ulonglong);
398     }
399 }
400
401 // Tell LLVM to emit the information necessary to unwind the stack for the
402 // function f.
403 fn set_uwtable(f: ValueRef) {
404     unsafe {
405         llvm::LLVMAddFunctionAttr(f,
406                                   lib::llvm::UWTableAttribute as c_ulonglong,
407                                   0u as c_ulonglong);
408     }
409 }
410
411 fn set_inline_hint(f: ValueRef) {
412     unsafe {
413         llvm::LLVMAddFunctionAttr(f, lib::llvm::InlineHintAttribute
414                                   as c_ulonglong, 0u as c_ulonglong);
415     }
416 }
417
418 fn set_inline_hint_if_appr(attrs: ~[ast::attribute],
419                            llfn: ValueRef) {
420     match attr::find_inline_attr(attrs) {
421       attr::ia_hint => set_inline_hint(llfn),
422       attr::ia_always => set_always_inline(llfn),
423       attr::ia_never => set_no_inline(llfn),
424       attr::ia_none => { /* fallthrough */ }
425     }
426 }
427
428 fn set_always_inline(f: ValueRef) {
429     unsafe {
430         llvm::LLVMAddFunctionAttr(f, lib::llvm::AlwaysInlineAttribute
431                                   as c_ulonglong, 0u as c_ulonglong);
432     }
433 }
434
435 fn set_custom_stack_growth_fn(f: ValueRef) {
436     unsafe {
437         llvm::LLVMAddFunctionAttr(f, 0u as c_ulonglong, 1u as c_ulonglong);
438     }
439 }
440
441 fn set_glue_inlining(f: ValueRef, t: ty::t) {
442     if ty::type_is_structural(t) {
443         set_no_inline(f);
444     } else { set_always_inline(f); }
445 }
446
447 // Double-check that we never ask LLVM to declare the same symbol twice. It
448 // silently mangles such symbols, breaking our linkage model.
449 fn note_unique_llvm_symbol(ccx: @crate_ctxt, +sym: ~str) {
450     // XXX: Bad copy.
451     if ccx.all_llvm_symbols.contains_key(copy sym) {
452         ccx.sess.bug(~"duplicate LLVM symbol: " + sym);
453     }
454     ccx.all_llvm_symbols.insert(sym, ());
455 }
456
457
458 fn get_res_dtor(ccx: @crate_ctxt, did: ast::def_id,
459                 parent_id: ast::def_id, substs: ~[ty::t])
460    -> ValueRef {
461     let _icx = ccx.insn_ctxt("trans_res_dtor");
462     if (substs.is_not_empty()) {
463         let did = if did.crate != ast::local_crate {
464             inline::maybe_instantiate_inline(ccx, did, true)
465         } else { did };
466         assert did.crate == ast::local_crate;
467         monomorphize::monomorphic_fn(ccx, did, substs, None, None, None).val
468     } else if did.crate == ast::local_crate {
469         get_item_val(ccx, did.node)
470     } else {
471         let tcx = ccx.tcx;
472         let name = csearch::get_symbol(ccx.sess.cstore, did);
473         let class_ty = ty::subst_tps(tcx, substs, None,
474                           ty::lookup_item_type(tcx, parent_id).ty);
475         let llty = type_of_dtor(ccx, class_ty);
476         get_extern_fn(ccx.externs, ccx.llmod, name, lib::llvm::CCallConv,
477                       llty)
478     }
479 }
480
481 // Structural comparison: a rather involved form of glue.
482 fn maybe_name_value(cx: @crate_ctxt, v: ValueRef, s: ~str) {
483     if cx.sess.opts.save_temps {
484         let _: () = str::as_c_str(s, |buf| {
485             unsafe {
486                 llvm::LLVMSetValueName(v, buf)
487             }
488         });
489     }
490 }
491
492
493 // Used only for creating scalar comparison glue.
494 enum scalar_type { nil_type, signed_int, unsigned_int, floating_point, }
495
496 fn compare_scalar_types(cx: block, lhs: ValueRef, rhs: ValueRef,
497                         t: ty::t, op: ast::binop) -> Result {
498     let f = |a| compare_scalar_values(cx, lhs, rhs, a, op);
499
500     match ty::get(t).sty {
501         ty::ty_nil => rslt(cx, f(nil_type)),
502         ty::ty_bool | ty::ty_ptr(_) => rslt(cx, f(unsigned_int)),
503         ty::ty_int(_) => rslt(cx, f(signed_int)),
504         ty::ty_uint(_) => rslt(cx, f(unsigned_int)),
505         ty::ty_float(_) => rslt(cx, f(floating_point)),
506         ty::ty_type => {
507             rslt(
508                 controlflow::trans_fail(
509                     cx, None,
510                     ~"attempt to compare values of type type"),
511                 C_nil())
512         }
513         _ => {
514             // Should never get here, because t is scalar.
515             cx.sess().bug(~"non-scalar type passed to \
516                             compare_scalar_types")
517         }
518     }
519 }
520
521
522 // A helper function to do the actual comparison of scalar values.
523 fn compare_scalar_values(cx: block, lhs: ValueRef, rhs: ValueRef,
524                          nt: scalar_type, op: ast::binop) -> ValueRef {
525     let _icx = cx.insn_ctxt("compare_scalar_values");
526     fn die(cx: block) -> ! {
527         cx.tcx().sess.bug(~"compare_scalar_values: must be a\
528           comparison operator");
529     }
530     match nt {
531       nil_type => {
532         // We don't need to do actual comparisons for nil.
533         // () == () holds but () < () does not.
534         match op {
535           ast::eq | ast::le | ast::ge => return C_bool(true),
536           ast::ne | ast::lt | ast::gt => return C_bool(false),
537           // refinements would be nice
538           _ => die(cx)
539         }
540       }
541       floating_point => {
542         let cmp = match op {
543           ast::eq => lib::llvm::RealOEQ,
544           ast::ne => lib::llvm::RealUNE,
545           ast::lt => lib::llvm::RealOLT,
546           ast::le => lib::llvm::RealOLE,
547           ast::gt => lib::llvm::RealOGT,
548           ast::ge => lib::llvm::RealOGE,
549           _ => die(cx)
550         };
551         return FCmp(cx, cmp, lhs, rhs);
552       }
553       signed_int => {
554         let cmp = match op {
555           ast::eq => lib::llvm::IntEQ,
556           ast::ne => lib::llvm::IntNE,
557           ast::lt => lib::llvm::IntSLT,
558           ast::le => lib::llvm::IntSLE,
559           ast::gt => lib::llvm::IntSGT,
560           ast::ge => lib::llvm::IntSGE,
561           _ => die(cx)
562         };
563         return ICmp(cx, cmp, lhs, rhs);
564       }
565       unsigned_int => {
566         let cmp = match op {
567           ast::eq => lib::llvm::IntEQ,
568           ast::ne => lib::llvm::IntNE,
569           ast::lt => lib::llvm::IntULT,
570           ast::le => lib::llvm::IntULE,
571           ast::gt => lib::llvm::IntUGT,
572           ast::ge => lib::llvm::IntUGE,
573           _ => die(cx)
574         };
575         return ICmp(cx, cmp, lhs, rhs);
576       }
577     }
578 }
579
580 type val_pair_fn = fn@(block, ValueRef, ValueRef) -> block;
581 type val_and_ty_fn = fn@(block, ValueRef, ty::t) -> block;
582
583 fn load_inbounds(cx: block, p: ValueRef, idxs: &[uint]) -> ValueRef {
584     return Load(cx, GEPi(cx, p, idxs));
585 }
586
587 fn store_inbounds(cx: block, v: ValueRef, p: ValueRef, idxs: &[uint]) {
588     Store(cx, v, GEPi(cx, p, idxs));
589 }
590
591 // Iterates through the elements of a structural type.
592 fn iter_structural_ty(cx: block, av: ValueRef, t: ty::t,
593                       f: val_and_ty_fn) -> block {
594     let _icx = cx.insn_ctxt("iter_structural_ty");
595
596     fn iter_variant(cx: block, a_tup: ValueRef,
597                     variant: ty::VariantInfo,
598                     tps: ~[ty::t], tid: ast::def_id,
599                     f: val_and_ty_fn) -> block {
600         let _icx = cx.insn_ctxt("iter_variant");
601         if variant.args.len() == 0u { return cx; }
602         let fn_ty = variant.ctor_ty;
603         let ccx = cx.ccx();
604         let mut cx = cx;
605         match ty::get(fn_ty).sty {
606           ty::ty_fn(ref fn_ty) => {
607             let mut j = 0u;
608             let v_id = variant.id;
609             for vec::each(fn_ty.sig.inputs) |a| {
610                 let llfldp_a = GEP_enum(cx, a_tup, tid, v_id,
611                                         /*bad*/copy tps, j);
612                 // XXX: Is "None" right here?
613                 let ty_subst = ty::subst_tps(ccx.tcx, tps, None, a.ty);
614                 cx = f(cx, llfldp_a, ty_subst);
615                 j += 1u;
616             }
617           }
618           _ => cx.tcx().sess.bug(fmt!("iter_variant: not a function type: \
619                                        %s (variant name = %s)",
620                                       cx.ty_to_str(fn_ty),
621                                       cx.sess().str_of(variant.name)))
622         }
623         return cx;
624     }
625
626     let mut cx = cx;
627     match /*bad*/copy ty::get(t).sty {
628       ty::ty_rec(*) | ty::ty_struct(*) => {
629           do expr::with_field_tys(cx.tcx(), t, None) |_has_dtor, field_tys| {
630               for vec::eachi(field_tys) |i, field_ty| {
631                   let llfld_a = GEPi(cx, av, struct_field(i));
632                   cx = f(cx, llfld_a, field_ty.mt.ty);
633               }
634           }
635       }
636       ty::ty_estr(ty::vstore_fixed(_)) |
637       ty::ty_evec(_, ty::vstore_fixed(_)) => {
638         let (base, len) = tvec::get_base_and_len(cx, av, t);
639         cx = tvec::iter_vec_raw(cx, base, t, len, f);
640       }
641       ty::ty_tup(args) => {
642         for vec::eachi(args) |i, arg| {
643             let llfld_a = GEPi(cx, av, [0u, i]);
644             cx = f(cx, llfld_a, *arg);
645         }
646       }
647       ty::ty_enum(tid, ref substs) => {
648         let variants = ty::enum_variants(cx.tcx(), tid);
649         let n_variants = (*variants).len();
650
651         // Cast the enums to types we can GEP into.
652         if n_variants == 1u {
653             return iter_variant(cx,
654                                 av,
655                                 variants[0],
656                                 /*bad*/copy substs.tps,
657                                 tid,
658                                 f);
659         }
660
661         let ccx = cx.ccx();
662         let llenumty = T_opaque_enum_ptr(ccx);
663         let av_enum = PointerCast(cx, av, llenumty);
664         let lldiscrim_a_ptr = GEPi(cx, av_enum, [0u, 0u]);
665         let llunion_a_ptr = GEPi(cx, av_enum, [0u, 1u]);
666         let lldiscrim_a = Load(cx, lldiscrim_a_ptr);
667
668         // NB: we must hit the discriminant first so that structural
669         // comparison know not to proceed when the discriminants differ.
670         cx = f(cx, lldiscrim_a_ptr, ty::mk_int(cx.tcx()));
671         let unr_cx = sub_block(cx, ~"enum-iter-unr");
672         Unreachable(unr_cx);
673         let llswitch = Switch(cx, lldiscrim_a, unr_cx.llbb, n_variants);
674         let next_cx = sub_block(cx, ~"enum-iter-next");
675         for vec::each(*variants) |variant| {
676             let variant_cx =
677                 sub_block(cx,
678                                    ~"enum-iter-variant-" +
679                                        int::to_str(variant.disr_val, 10u));
680             AddCase(llswitch, C_int(ccx, variant.disr_val), variant_cx.llbb);
681             let variant_cx =
682                 iter_variant(variant_cx, llunion_a_ptr, *variant,
683                              /*bad*/copy (*substs).tps, tid, f);
684             Br(variant_cx, next_cx.llbb);
685         }
686         return next_cx;
687       }
688       _ => cx.sess().unimpl(~"type in iter_structural_ty")
689     }
690     return cx;
691 }
692
693 fn cast_shift_expr_rhs(cx: block, op: ast::binop,
694                        lhs: ValueRef, rhs: ValueRef) -> ValueRef {
695     cast_shift_rhs(op, lhs, rhs,
696                    |a,b| Trunc(cx, a, b),
697                    |a,b| ZExt(cx, a, b))
698 }
699
700 fn cast_shift_const_rhs(op: ast::binop,
701                         lhs: ValueRef, rhs: ValueRef) -> ValueRef {
702     unsafe {
703         cast_shift_rhs(op, lhs, rhs,
704                        |a, b| unsafe { llvm::LLVMConstTrunc(a, b) },
705                        |a, b| unsafe { llvm::LLVMConstZExt(a, b) })
706     }
707 }
708
709 fn cast_shift_rhs(op: ast::binop,
710                   lhs: ValueRef, rhs: ValueRef,
711                   trunc: fn(ValueRef, TypeRef) -> ValueRef,
712                   zext: fn(ValueRef, TypeRef) -> ValueRef
713                  ) -> ValueRef {
714     // Shifts may have any size int on the rhs
715     unsafe {
716         if ast_util::is_shift_binop(op) {
717             let rhs_llty = val_ty(rhs);
718             let lhs_llty = val_ty(lhs);
719             let rhs_sz = llvm::LLVMGetIntTypeWidth(rhs_llty);
720             let lhs_sz = llvm::LLVMGetIntTypeWidth(lhs_llty);
721             if lhs_sz < rhs_sz {
722                 trunc(rhs, lhs_llty)
723             } else if lhs_sz > rhs_sz {
724                 // FIXME (#1877: If shifting by negative
725                 // values becomes not undefined then this is wrong.
726                 zext(rhs, lhs_llty)
727             } else {
728                 rhs
729             }
730         } else {
731             rhs
732         }
733     }
734 }
735
736 fn fail_if_zero(cx: block, span: span, divmod: ast::binop,
737                 rhs: ValueRef, rhs_t: ty::t) -> block {
738     let text = if divmod == ast::div {
739         ~"divide by zero"
740     } else {
741         ~"modulo zero"
742     };
743     let is_zero = match ty::get(rhs_t).sty {
744       ty::ty_int(t) => {
745         let zero = C_integral(T_int_ty(cx.ccx(), t), 0u64, False);
746         ICmp(cx, lib::llvm::IntEQ, rhs, zero)
747       }
748       ty::ty_uint(t) => {
749         let zero = C_integral(T_uint_ty(cx.ccx(), t), 0u64, False);
750         ICmp(cx, lib::llvm::IntEQ, rhs, zero)
751       }
752       _ => {
753         cx.tcx().sess.bug(~"fail-if-zero on unexpected type: " +
754                           ty_to_str(cx.ccx().tcx, rhs_t));
755       }
756     };
757     do with_cond(cx, is_zero) |bcx| {
758         controlflow::trans_fail(bcx, Some(span), /*bad*/copy text)
759     }
760 }
761
762 fn null_env_ptr(bcx: block) -> ValueRef {
763     C_null(T_opaque_box_ptr(bcx.ccx()))
764 }
765
766 fn trans_external_path(ccx: @crate_ctxt, did: ast::def_id, t: ty::t)
767     -> ValueRef {
768     let name = csearch::get_symbol(ccx.sess.cstore, did);
769     match ty::get(t).sty {
770       ty::ty_fn(_) => {
771         let llty = type_of_fn_from_ty(ccx, t);
772         return get_extern_fn(ccx.externs, ccx.llmod, name,
773                           lib::llvm::CCallConv, llty);
774       }
775       _ => {
776         let llty = type_of(ccx, t);
777         return get_extern_const(ccx.externs, ccx.llmod, name, llty);
778       }
779     };
780 }
781
782 fn get_discrim_val(cx: @crate_ctxt, span: span, enum_did: ast::def_id,
783                    variant_did: ast::def_id) -> ValueRef {
784     // Can't use `discrims` from the crate context here because
785     // those discriminants have an extra level of indirection,
786     // and there's no LLVM constant load instruction.
787     let mut lldiscrim_opt = None;
788     for ty::enum_variants(cx.tcx, enum_did).each |variant_info| {
789         if variant_info.id == variant_did {
790             lldiscrim_opt = Some(C_int(cx,
791                                        variant_info.disr_val));
792             break;
793         }
794     }
795
796     match lldiscrim_opt {
797         None => {
798             cx.tcx.sess.span_bug(span, ~"didn't find discriminant?!");
799         }
800         Some(found_lldiscrim) => {
801             found_lldiscrim
802         }
803     }
804 }
805
806 fn lookup_discriminant(ccx: @crate_ctxt, vid: ast::def_id) -> ValueRef {
807     unsafe {
808         let _icx = ccx.insn_ctxt("lookup_discriminant");
809         match ccx.discrims.find(vid) {
810             None => {
811                 // It's an external discriminant that we haven't seen yet.
812                 assert (vid.crate != ast::local_crate);
813                 let sym = csearch::get_symbol(ccx.sess.cstore, vid);
814                 let gvar = str::as_c_str(sym, |buf| {
815                     llvm::LLVMAddGlobal(ccx.llmod, ccx.int_type, buf)
816                 });
817                 lib::llvm::SetLinkage(gvar, lib::llvm::ExternalLinkage);
818                 llvm::LLVMSetGlobalConstant(gvar, True);
819                 ccx.discrims.insert(vid, gvar);
820                 return gvar;
821             }
822             Some(llval) => return llval,
823         }
824     }
825 }
826
827 fn invoke(bcx: block, llfn: ValueRef, +llargs: ~[ValueRef]) -> block {
828     let _icx = bcx.insn_ctxt("invoke_");
829     if bcx.unreachable { return bcx; }
830     if need_invoke(bcx) {
831         log(debug, ~"invoking");
832         let normal_bcx = sub_block(bcx, ~"normal return");
833         Invoke(bcx, llfn, llargs, normal_bcx.llbb, get_landing_pad(bcx));
834         return normal_bcx;
835     } else {
836         log(debug, ~"calling");
837         Call(bcx, llfn, llargs);
838         return bcx;
839     }
840 }
841
842 fn need_invoke(bcx: block) -> bool {
843     if (bcx.ccx().sess.opts.debugging_opts & session::no_landing_pads != 0) {
844         return false;
845     }
846
847     // Avoid using invoke if we are already inside a landing pad.
848     if bcx.is_lpad {
849         return false;
850     }
851
852     if have_cached_lpad(bcx) {
853         return true;
854     }
855
856     // Walk the scopes to look for cleanups
857     let mut cur = bcx;
858     loop {
859         match cur.kind {
860           block_scope(ref inf) => {
861             for vec::each((*inf).cleanups) |cleanup| {
862                 match *cleanup {
863                   clean(_, cleanup_type) | clean_temp(_, _, cleanup_type) => {
864                     if cleanup_type == normal_exit_and_unwind {
865                         return true;
866                     }
867                   }
868                 }
869             }
870           }
871           _ => ()
872         }
873         cur = match cur.parent {
874           Some(next) => next,
875           None => return false
876         }
877     }
878 }
879
880 fn have_cached_lpad(bcx: block) -> bool {
881     let mut res = false;
882     do in_lpad_scope_cx(bcx) |inf| {
883         match inf.landing_pad {
884           Some(_) => res = true,
885           None => res = false
886         }
887     }
888     return res;
889 }
890
891 fn in_lpad_scope_cx(bcx: block, f: fn(scope_info)) {
892     let mut bcx = bcx;
893     loop {
894         match bcx.kind {
895           block_scope(ref inf) => {
896             if (*inf).cleanups.len() > 0u || bcx.parent.is_none() {
897                 f((*inf)); return;
898             }
899           }
900           _ => ()
901         }
902         bcx = block_parent(bcx);
903     }
904 }
905
906 fn get_landing_pad(bcx: block) -> BasicBlockRef {
907     let _icx = bcx.insn_ctxt("get_landing_pad");
908
909     let mut cached = None, pad_bcx = bcx; // Guaranteed to be set below
910     do in_lpad_scope_cx(bcx) |inf| {
911         // If there is a valid landing pad still around, use it
912         match copy inf.landing_pad {
913           Some(target) => cached = Some(target),
914           None => {
915             pad_bcx = lpad_block(bcx, ~"unwind");
916             inf.landing_pad = Some(pad_bcx.llbb);
917           }
918         }
919     }
920     // Can't return from block above
921     match cached { Some(b) => return b, None => () }
922     // The landing pad return type (the type being propagated). Not sure what
923     // this represents but it's determined by the personality function and
924     // this is what the EH proposal example uses.
925     let llretty = T_struct(~[T_ptr(T_i8()), T_i32()]);
926     // The exception handling personality function. This is the C++
927     // personality function __gxx_personality_v0, wrapped in our naming
928     // convention.
929     let personality = bcx.ccx().upcalls.rust_personality;
930     // The only landing pad clause will be 'cleanup'
931     let llretval = LandingPad(pad_bcx, llretty, personality, 1u);
932     // The landing pad block is a cleanup
933     SetCleanup(pad_bcx, llretval);
934
935     // Because we may have unwound across a stack boundary, we must call into
936     // the runtime to figure out which stack segment we are on and place the
937     // stack limit back into the TLS.
938     Call(pad_bcx, bcx.ccx().upcalls.reset_stack_limit, ~[]);
939
940     // We store the retval in a function-central alloca, so that calls to
941     // Resume can find it.
942     match copy bcx.fcx.personality {
943       Some(addr) => Store(pad_bcx, llretval, addr),
944       None => {
945         let addr = alloca(pad_bcx, val_ty(llretval));
946         bcx.fcx.personality = Some(addr);
947         Store(pad_bcx, llretval, addr);
948       }
949     }
950
951     // Unwind all parent scopes, and finish with a Resume instr
952     cleanup_and_leave(pad_bcx, None, None);
953     return pad_bcx.llbb;
954 }
955
956 // Arranges for the value found in `*root_loc` to be dropped once the scope
957 // associated with `scope_id` exits.  This is used to keep boxes live when
958 // there are extant region pointers pointing at the interior.
959 //
960 // Note that `root_loc` is not the value itself but rather a pointer to the
961 // value.  Generally it in alloca'd value.  The reason for this is that the
962 // value is initialized in an inner block but may be freed in some outer
963 // block, so an SSA value that is valid in the inner block may not be valid in
964 // the outer block.  In fact, the inner block may not even execute.  Rather
965 // than generate the full SSA form, we just use an alloca'd value.
966 fn add_root_cleanup(bcx: block, scope_id: ast::node_id,
967                     root_loc: ValueRef, ty: ty::t) {
968
969     debug!("add_root_cleanup(bcx=%s, scope_id=%d, root_loc=%s, ty=%s)",
970            bcx.to_str(), scope_id, val_str(bcx.ccx().tn, root_loc),
971            ppaux::ty_to_str(bcx.ccx().tcx, ty));
972
973     let bcx_scope = find_bcx_for_scope(bcx, scope_id);
974     add_clean_temp_mem(bcx_scope, root_loc, ty);
975
976     fn find_bcx_for_scope(bcx: block, scope_id: ast::node_id) -> block {
977         let mut bcx_sid = bcx;
978         loop {
979             bcx_sid = match bcx_sid.node_info {
980               Some({id, _}) if id == scope_id => {
981                 return bcx_sid
982               }
983               _ => {
984                 match bcx_sid.parent {
985                   None => bcx.tcx().sess.bug(
986                       fmt!("no enclosing scope with id %d", scope_id)),
987                   Some(bcx_par) => bcx_par
988                 }
989               }
990             }
991         }
992     }
993 }
994
995 fn do_spill(bcx: block, v: ValueRef, t: ty::t) -> ValueRef {
996     if ty::type_is_bot(t) {
997         return C_null(T_ptr(T_i8()));
998     }
999     let llptr = alloc_ty(bcx, t);
1000     Store(bcx, v, llptr);
1001     return llptr;
1002 }
1003
1004 // Since this function does *not* root, it is the caller's responsibility to
1005 // ensure that the referent is pointed to by a root.
1006 // [Note-arg-mode]
1007 // ++ mode is temporary, due to how borrowck treats enums. With hope,
1008 // will go away anyway when we get rid of modes.
1009 fn do_spill_noroot(++cx: block, v: ValueRef) -> ValueRef {
1010     let llptr = alloca(cx, val_ty(v));
1011     Store(cx, v, llptr);
1012     return llptr;
1013 }
1014
1015 fn spill_if_immediate(cx: block, v: ValueRef, t: ty::t) -> ValueRef {
1016     let _icx = cx.insn_ctxt("spill_if_immediate");
1017     if ty::type_is_immediate(t) { return do_spill(cx, v, t); }
1018     return v;
1019 }
1020
1021 fn load_if_immediate(cx: block, v: ValueRef, t: ty::t) -> ValueRef {
1022     let _icx = cx.insn_ctxt("load_if_immediate");
1023     if ty::type_is_immediate(t) { return Load(cx, v); }
1024     return v;
1025 }
1026
1027 fn trans_trace(bcx: block, sp_opt: Option<span>, +trace_str: ~str) {
1028     if !bcx.sess().trace() { return; }
1029     let _icx = bcx.insn_ctxt("trans_trace");
1030     // XXX: Bad copy.
1031     add_comment(bcx, copy trace_str);
1032     let V_trace_str = C_cstr(bcx.ccx(), trace_str);
1033     let {V_filename, V_line} = match sp_opt {
1034       Some(sp) => {
1035         let sess = bcx.sess();
1036         let loc = sess.parse_sess.cm.lookup_char_pos(sp.lo);
1037         {V_filename: C_cstr(bcx.ccx(), /*bad*/copy loc.file.name),
1038          V_line: loc.line as int}
1039       }
1040       None => {
1041         {V_filename: C_cstr(bcx.ccx(), ~"<runtime>"),
1042          V_line: 0}
1043       }
1044     };
1045     let ccx = bcx.ccx();
1046     let V_trace_str = PointerCast(bcx, V_trace_str, T_ptr(T_i8()));
1047     let V_filename = PointerCast(bcx, V_filename, T_ptr(T_i8()));
1048     let args = ~[V_trace_str, V_filename, C_int(ccx, V_line)];
1049     Call(bcx, ccx.upcalls.trace, args);
1050 }
1051
1052 fn build_return(bcx: block) {
1053     let _icx = bcx.insn_ctxt("build_return");
1054     Br(bcx, bcx.fcx.llreturn);
1055 }
1056
1057 fn ignore_lhs(_bcx: block, local: @ast::local) -> bool {
1058     match local.node.pat.node {
1059         ast::pat_wild => true, _ => false
1060     }
1061 }
1062
1063 fn init_local(bcx: block, local: @ast::local) -> block {
1064
1065     debug!("init_local(bcx=%s, local.id=%?)",
1066            bcx.to_str(), local.node.id);
1067     let _indenter = indenter();
1068
1069     let _icx = bcx.insn_ctxt("init_local");
1070     let ty = node_id_type(bcx, local.node.id);
1071
1072     debug!("ty=%s", bcx.ty_to_str(ty));
1073
1074     if ignore_lhs(bcx, local) {
1075         // Handle let _ = e; just like e;
1076         match local.node.init {
1077             Some(init) => {
1078               return expr::trans_into(bcx, init, expr::Ignore);
1079             }
1080             None => { return bcx; }
1081         }
1082     }
1083
1084     let llptr = match bcx.fcx.lllocals.find(local.node.id) {
1085       Some(local_mem(v)) => v,
1086       _ => { bcx.tcx().sess.span_bug(local.span,
1087                         ~"init_local: Someone forgot to document why it's\
1088                          safe to assume local.node.init must be local_mem!");
1089         }
1090     };
1091
1092     let mut bcx = bcx;
1093     match local.node.init {
1094         Some(init) => {
1095             bcx = expr::trans_into(bcx, init, expr::SaveIn(llptr));
1096         }
1097         _ => {
1098             zero_mem(bcx, llptr, ty);
1099         }
1100     }
1101
1102     // Make a note to drop this slot on the way out.
1103     debug!("adding clean for %?/%s to bcx=%s",
1104            local.node.id, bcx.ty_to_str(ty),
1105            bcx.to_str());
1106     add_clean(bcx, llptr, ty);
1107
1108     return _match::bind_irrefutable_pat(bcx,
1109                                        local.node.pat,
1110                                        llptr,
1111                                        false,
1112                                        _match::BindLocal);
1113 }
1114
1115 fn trans_stmt(cx: block, s: ast::stmt) -> block {
1116     let _icx = cx.insn_ctxt("trans_stmt");
1117     debug!("trans_stmt(%s)", stmt_to_str(s, cx.tcx().sess.intr()));
1118
1119     if !cx.sess().no_asm_comments() {
1120         add_span_comment(cx, s.span, stmt_to_str(s, cx.ccx().sess.intr()));
1121     }
1122
1123     let mut bcx = cx;
1124     debuginfo::update_source_pos(cx, s.span);
1125
1126     match s.node {
1127         ast::stmt_expr(e, _) | ast::stmt_semi(e, _) => {
1128             bcx = expr::trans_into(cx, e, expr::Ignore);
1129         }
1130         ast::stmt_decl(d, _) => {
1131             match /*bad*/copy d.node {
1132                 ast::decl_local(locals) => {
1133                     for vec::each(locals) |local| {
1134                         bcx = init_local(bcx, *local);
1135                         if cx.sess().opts.extra_debuginfo {
1136                             debuginfo::create_local_var(bcx, *local);
1137                         }
1138                     }
1139                 }
1140                 ast::decl_item(i) => trans_item(cx.fcx.ccx, *i)
1141             }
1142         }
1143         ast::stmt_mac(*) => cx.tcx().sess.bug(~"unexpanded macro")
1144     }
1145
1146     return bcx;
1147 }
1148
1149 // You probably don't want to use this one. See the
1150 // next three functions instead.
1151 fn new_block(cx: fn_ctxt, parent: Option<block>, +kind: block_kind,
1152              is_lpad: bool, +name: ~str, opt_node_info: Option<node_info>)
1153     -> block {
1154
1155     let s = if cx.ccx.sess.opts.save_temps || cx.ccx.sess.opts.debuginfo {
1156         (cx.ccx.names)(name)
1157     } else {
1158         special_idents::invalid
1159     };
1160     unsafe {
1161         let llbb: BasicBlockRef = str::as_c_str(cx.ccx.sess.str_of(s), |buf| {
1162             llvm::LLVMAppendBasicBlock(cx.llfn, buf)
1163         });
1164         let bcx = mk_block(llbb,
1165                            parent,
1166                            move kind,
1167                            is_lpad,
1168                            opt_node_info,
1169                            cx);
1170         do option::iter(&parent) |cx| {
1171             if cx.unreachable { Unreachable(bcx); }
1172         };
1173         return bcx;
1174     }
1175 }
1176
1177 fn simple_block_scope() -> block_kind {
1178     block_scope(scope_info {
1179         loop_break: None,
1180         loop_label: None,
1181         mut cleanups: ~[],
1182         mut cleanup_paths: ~[],
1183         mut landing_pad: None
1184     })
1185 }
1186
1187 // Use this when you're at the top block of a function or the like.
1188 fn top_scope_block(fcx: fn_ctxt, opt_node_info: Option<node_info>) -> block {
1189     return new_block(fcx, None, simple_block_scope(), false,
1190                   ~"function top level", opt_node_info);
1191 }
1192
1193 fn scope_block(bcx: block,
1194                opt_node_info: Option<node_info>,
1195                +n: ~str) -> block {
1196     return new_block(bcx.fcx, Some(bcx), simple_block_scope(), bcx.is_lpad,
1197                   n, opt_node_info);
1198 }
1199
1200 fn loop_scope_block(bcx: block, loop_break: block, loop_label: Option<ident>,
1201                     +n: ~str, opt_node_info: Option<node_info>) -> block {
1202     return new_block(bcx.fcx, Some(bcx), block_scope(scope_info {
1203         loop_break: Some(loop_break),
1204         loop_label: loop_label,
1205         mut cleanups: ~[],
1206         mut cleanup_paths: ~[],
1207         mut landing_pad: None
1208     }), bcx.is_lpad, n, opt_node_info);
1209 }
1210
1211 // Use this when creating a block for the inside of a landing pad.
1212 fn lpad_block(bcx: block, +n: ~str) -> block {
1213     new_block(bcx.fcx, Some(bcx), block_non_scope, true, n, None)
1214 }
1215
1216 // Use this when you're making a general CFG BB within a scope.
1217 fn sub_block(bcx: block, +n: ~str) -> block {
1218     new_block(bcx.fcx, Some(bcx), block_non_scope, bcx.is_lpad, n, None)
1219 }
1220
1221 fn raw_block(fcx: fn_ctxt, is_lpad: bool, llbb: BasicBlockRef) -> block {
1222     mk_block(llbb, None, block_non_scope, is_lpad, None, fcx)
1223 }
1224
1225
1226 // trans_block_cleanups: Go through all the cleanups attached to this
1227 // block and execute them.
1228 //
1229 // When translating a block that introduces new variables during its scope, we
1230 // need to make sure those variables go out of scope when the block ends.  We
1231 // do that by running a 'cleanup' function for each variable.
1232 // trans_block_cleanups runs all the cleanup functions for the block.
1233 fn trans_block_cleanups(bcx: block, +cleanups: ~[cleanup]) -> block {
1234     trans_block_cleanups_(bcx, cleanups, false)
1235 }
1236
1237 fn trans_block_cleanups_(bcx: block,
1238                          +cleanups: ~[cleanup],
1239                          /* cleanup_cx: block, */ is_lpad: bool) ->
1240    block {
1241     let _icx = bcx.insn_ctxt("trans_block_cleanups");
1242     // NB: Don't short-circuit even if this block is unreachable because
1243     // GC-based cleanup needs to the see that the roots are live.
1244     let no_lpads =
1245         bcx.ccx().sess.opts.debugging_opts & session::no_landing_pads != 0;
1246     if bcx.unreachable && !no_lpads { return bcx; }
1247     let mut bcx = bcx;
1248     for vec::rev_each(cleanups) |cu| {
1249         match *cu {
1250             clean(cfn, cleanup_type) | clean_temp(_, cfn, cleanup_type) => {
1251                 // Some types don't need to be cleaned up during
1252                 // landing pads because they can be freed en mass later
1253                 if cleanup_type == normal_exit_and_unwind || !is_lpad {
1254                     bcx = cfn(bcx);
1255                 }
1256             }
1257         }
1258     }
1259     return bcx;
1260 }
1261
1262 // In the last argument, Some(block) mean jump to this block, and none means
1263 // this is a landing pad and leaving should be accomplished with a resume
1264 // instruction.
1265 fn cleanup_and_leave(bcx: block, upto: Option<BasicBlockRef>,
1266                      leave: Option<BasicBlockRef>) {
1267     let _icx = bcx.insn_ctxt("cleanup_and_leave");
1268     let mut cur = bcx, bcx = bcx;
1269     let is_lpad = leave == None;
1270     loop {
1271         debug!("cleanup_and_leave: leaving %s", cur.to_str());
1272
1273         if bcx.sess().trace() {
1274             trans_trace(
1275                 bcx, None,
1276                 fmt!("cleanup_and_leave(%s)", cur.to_str()));
1277         }
1278
1279         match cur.kind {
1280           block_scope(ref inf) if (*inf).cleanups.len() > 0u => {
1281             for vec::find((*inf).cleanup_paths,
1282                           |cp| cp.target == leave).each |cp| {
1283                 Br(bcx, cp.dest);
1284                 return;
1285             }
1286             let sub_cx = sub_block(bcx, ~"cleanup");
1287             Br(bcx, sub_cx.llbb);
1288             (*inf).cleanup_paths.push({target: leave, dest: sub_cx.llbb});
1289             bcx = trans_block_cleanups_(sub_cx, block_cleanups(cur), is_lpad);
1290           }
1291           _ => ()
1292         }
1293         match upto {
1294           Some(bb) => { if cur.llbb == bb { break; } }
1295           _ => ()
1296         }
1297         cur = match cur.parent {
1298           Some(next) => next,
1299           None => { assert upto.is_none(); break; }
1300         };
1301     }
1302     match leave {
1303       Some(target) => Br(bcx, target),
1304       None => { Resume(bcx, Load(bcx, bcx.fcx.personality.get())); }
1305     }
1306 }
1307
1308 fn cleanup_and_Br(bcx: block, upto: block,
1309                   target: BasicBlockRef) {
1310     let _icx = bcx.insn_ctxt("cleanup_and_Br");
1311     cleanup_and_leave(bcx, Some(upto.llbb), Some(target));
1312 }
1313
1314 fn leave_block(bcx: block, out_of: block) -> block {
1315     let _icx = bcx.insn_ctxt("leave_block");
1316     let next_cx = sub_block(block_parent(out_of), ~"next");
1317     if bcx.unreachable { Unreachable(next_cx); }
1318     cleanup_and_Br(bcx, out_of, next_cx.llbb);
1319     next_cx
1320 }
1321
1322 fn with_scope(bcx: block, opt_node_info: Option<node_info>,
1323               +name: ~str, f: fn(block) -> block) -> block {
1324     let _icx = bcx.insn_ctxt("with_scope");
1325
1326     debug!("with_scope(bcx=%s, opt_node_info=%?, name=%s)",
1327            bcx.to_str(), opt_node_info, name);
1328     let _indenter = indenter();
1329
1330     let scope_cx = scope_block(bcx, opt_node_info, name);
1331     Br(bcx, scope_cx.llbb);
1332     leave_block(f(scope_cx), scope_cx)
1333 }
1334
1335 fn with_scope_result(bcx: block,
1336                      opt_node_info: Option<node_info>,
1337                      +name: ~str,
1338                      f: fn(block) -> Result)
1339                   -> Result {
1340     let _icx = bcx.insn_ctxt("with_scope_result");
1341     let scope_cx = scope_block(bcx, opt_node_info, name);
1342     Br(bcx, scope_cx.llbb);
1343     let Result {bcx, val} = f(scope_cx);
1344     rslt(leave_block(bcx, scope_cx), val)
1345 }
1346
1347 fn with_scope_datumblock(bcx: block, opt_node_info: Option<node_info>,
1348                          +name: ~str, f: fn(block) -> datum::DatumBlock)
1349     -> datum::DatumBlock
1350 {
1351     use middle::trans::datum::DatumBlock;
1352
1353     let _icx = bcx.insn_ctxt("with_scope_result");
1354     let scope_cx = scope_block(bcx, opt_node_info, name);
1355     Br(bcx, scope_cx.llbb);
1356     let DatumBlock {bcx, datum} = f(scope_cx);
1357     DatumBlock {bcx: leave_block(bcx, scope_cx), datum: datum}
1358 }
1359
1360 fn block_locals(b: ast::blk, it: fn(@ast::local)) {
1361     for vec::each(b.node.stmts) |s| {
1362         match s.node {
1363           ast::stmt_decl(d, _) => {
1364             match /*bad*/copy d.node {
1365               ast::decl_local(locals) => {
1366                 for vec::each(locals) |local| {
1367                     it(*local);
1368                 }
1369               }
1370               _ => {/* fall through */ }
1371             }
1372           }
1373           _ => {/* fall through */ }
1374         }
1375     }
1376 }
1377
1378 fn alloc_local(cx: block, local: @ast::local) -> block {
1379     let _icx = cx.insn_ctxt("alloc_local");
1380     let t = node_id_type(cx, local.node.id);
1381     let simple_name = match local.node.pat.node {
1382       ast::pat_ident(_, pth, None) => Some(path_to_ident(pth)),
1383       _ => None
1384     };
1385     let val = alloc_ty(cx, t);
1386     if cx.sess().opts.debuginfo {
1387         do option::iter(&simple_name) |name| {
1388             str::as_c_str(cx.ccx().sess.str_of(*name), |buf| {
1389                 unsafe {
1390                     llvm::LLVMSetValueName(val, buf)
1391                 }
1392             });
1393         }
1394     }
1395     cx.fcx.lllocals.insert(local.node.id, local_mem(val));
1396     return cx;
1397 }
1398
1399
1400 fn with_cond(bcx: block, val: ValueRef, f: fn(block) -> block) -> block {
1401     let _icx = bcx.insn_ctxt("with_cond");
1402     let next_cx = base::sub_block(bcx, ~"next");
1403     let cond_cx = base::sub_block(bcx, ~"cond");
1404     CondBr(bcx, val, cond_cx.llbb, next_cx.llbb);
1405     let after_cx = f(cond_cx);
1406     if !after_cx.terminated { Br(after_cx, next_cx.llbb); }
1407     next_cx
1408 }
1409
1410 fn call_memcpy(cx: block, dst: ValueRef, src: ValueRef,
1411                 n_bytes: ValueRef) {
1412     // FIXME (Related to #1645, I think?): Provide LLVM with better
1413     // alignment information when the alignment is statically known (it must
1414     // be nothing more than a constant int, or LLVM complains -- not even a
1415     // constant element of a tydesc works).
1416     let _icx = cx.insn_ctxt("call_memcpy");
1417     let ccx = cx.ccx();
1418     let key = match ccx.sess.targ_cfg.arch {
1419       session::arch_x86 | session::arch_arm => ~"llvm.memcpy.p0i8.p0i8.i32",
1420       session::arch_x86_64 => ~"llvm.memcpy.p0i8.p0i8.i64"
1421     };
1422     let memcpy = ccx.intrinsics.get(key);
1423     let src_ptr = PointerCast(cx, src, T_ptr(T_i8()));
1424     let dst_ptr = PointerCast(cx, dst, T_ptr(T_i8()));
1425     let size = IntCast(cx, n_bytes, ccx.int_type);
1426     let align = C_i32(1i32);
1427     let volatile = C_bool(false);
1428     Call(cx, memcpy, ~[dst_ptr, src_ptr, size, align, volatile]);
1429 }
1430
1431 fn memcpy_ty(bcx: block, dst: ValueRef, src: ValueRef, t: ty::t) {
1432     let _icx = bcx.insn_ctxt("memcpy_ty");
1433     let ccx = bcx.ccx();
1434     if ty::type_is_structural(t) {
1435         let llsz = llsize_of(ccx, type_of::type_of(ccx, t));
1436         call_memcpy(bcx, dst, src, llsz);
1437     } else {
1438         Store(bcx, Load(bcx, src), dst);
1439     }
1440 }
1441
1442 fn zero_mem(cx: block, llptr: ValueRef, t: ty::t) {
1443     let _icx = cx.insn_ctxt("zero_mem");
1444     let bcx = cx;
1445     let ccx = cx.ccx();
1446     let llty = type_of::type_of(ccx, t);
1447     memzero(bcx, llptr, llty);
1448 }
1449
1450 // Always use this function instead of storing a zero constant to the memory
1451 // in question. If you store a zero constant, LLVM will drown in vreg
1452 // allocation for large data structures, and the generated code will be
1453 // awful. (A telltale sign of this is large quantities of
1454 // `mov [byte ptr foo],0` in the generated code.)
1455 fn memzero(cx: block, llptr: ValueRef, llty: TypeRef) {
1456     let _icx = cx.insn_ctxt("memzero");
1457     let ccx = cx.ccx();
1458
1459     let intrinsic_key;
1460     match ccx.sess.targ_cfg.arch {
1461         session::arch_x86 | session::arch_arm => {
1462             intrinsic_key = ~"llvm.memset.p0i8.i32";
1463         }
1464         session::arch_x86_64 => {
1465             intrinsic_key = ~"llvm.memset.p0i8.i64";
1466         }
1467     }
1468
1469     let llintrinsicfn = ccx.intrinsics.get(intrinsic_key);
1470     let llptr = PointerCast(cx, llptr, T_ptr(T_i8()));
1471     let llzeroval = C_u8(0);
1472     let size = IntCast(cx, shape::llsize_of(ccx, llty), ccx.int_type);
1473     let align = C_i32(1i32);
1474     let volatile = C_bool(false);
1475     Call(cx, llintrinsicfn, ~[llptr, llzeroval, size, align, volatile]);
1476 }
1477
1478 fn alloc_ty(bcx: block, t: ty::t) -> ValueRef {
1479     let _icx = bcx.insn_ctxt("alloc_ty");
1480     let ccx = bcx.ccx();
1481     let llty = type_of::type_of(ccx, t);
1482     if ty::type_has_params(t) { log(error, ty_to_str(ccx.tcx, t)); }
1483     assert !ty::type_has_params(t);
1484     let val = alloca(bcx, llty);
1485     return val;
1486 }
1487
1488 fn alloca(cx: block, t: TypeRef) -> ValueRef {
1489     alloca_maybe_zeroed(cx, t, false)
1490 }
1491
1492 fn alloca_zeroed(cx: block, t: TypeRef) -> ValueRef {
1493     alloca_maybe_zeroed(cx, t, true)
1494 }
1495
1496 fn alloca_maybe_zeroed(cx: block, t: TypeRef, zero: bool) -> ValueRef {
1497     let _icx = cx.insn_ctxt("alloca");
1498     if cx.unreachable {
1499         unsafe {
1500             return llvm::LLVMGetUndef(t);
1501         }
1502     }
1503     let initcx = base::raw_block(cx.fcx, false, cx.fcx.llstaticallocas);
1504     let p = Alloca(initcx, t);
1505     if zero { memzero(initcx, p, t); }
1506     return p;
1507 }
1508
1509 fn arrayalloca(cx: block, t: TypeRef, v: ValueRef) -> ValueRef {
1510     let _icx = cx.insn_ctxt("arrayalloca");
1511     if cx.unreachable {
1512         unsafe {
1513             return llvm::LLVMGetUndef(t);
1514         }
1515     }
1516     return ArrayAlloca(
1517         base::raw_block(cx.fcx, false, cx.fcx.llstaticallocas), t, v);
1518 }
1519
1520 // Creates the standard set of basic blocks for a function
1521 fn mk_standard_basic_blocks(llfn: ValueRef) ->
1522    {sa: BasicBlockRef, rt: BasicBlockRef} {
1523     unsafe {
1524         {sa: str::as_c_str(~"static_allocas",
1525                            |buf| llvm::LLVMAppendBasicBlock(llfn, buf)),
1526          rt: str::as_c_str(~"return",
1527                            |buf| llvm::LLVMAppendBasicBlock(llfn, buf))}
1528     }
1529 }
1530
1531
1532 // NB: must keep 4 fns in sync:
1533 //
1534 //  - type_of_fn
1535 //  - create_llargs_for_fn_args.
1536 //  - new_fn_ctxt
1537 //  - trans_args
1538 fn new_fn_ctxt_w_id(ccx: @crate_ctxt,
1539                     +path: path,
1540                     llfndecl: ValueRef,
1541                     id: ast::node_id,
1542                     impl_id: Option<ast::def_id>,
1543                     +param_substs: Option<param_substs>,
1544                     sp: Option<span>) -> fn_ctxt {
1545     let llbbs = mk_standard_basic_blocks(llfndecl);
1546     return @fn_ctxt_ {
1547           llfn: llfndecl,
1548           llenv: unsafe { llvm::LLVMGetParam(llfndecl, 1u as c_uint) },
1549           llretptr: unsafe { llvm::LLVMGetParam(llfndecl, 0u as c_uint) },
1550           mut llstaticallocas: llbbs.sa,
1551           mut llloadenv: None,
1552           mut llreturn: llbbs.rt,
1553           mut llself: None,
1554           mut personality: None,
1555           mut loop_ret: None,
1556           llargs: HashMap(),
1557           lllocals: HashMap(),
1558           llupvars: HashMap(),
1559           id: id,
1560           impl_id: impl_id,
1561           param_substs: param_substs,
1562           span: sp,
1563           path: path,
1564           ccx: ccx
1565     };
1566 }
1567
1568 fn new_fn_ctxt(ccx: @crate_ctxt,
1569                +path: path,
1570                llfndecl: ValueRef,
1571                sp: Option<span>)
1572             -> fn_ctxt {
1573     return new_fn_ctxt_w_id(ccx, path, llfndecl, -1, None, None, sp);
1574 }
1575
1576 // NB: must keep 4 fns in sync:
1577 //
1578 //  - type_of_fn
1579 //  - create_llargs_for_fn_args.
1580 //  - new_fn_ctxt
1581 //  - trans_args
1582
1583 // create_llargs_for_fn_args: Creates a mapping from incoming arguments to
1584 // allocas created for them.
1585 //
1586 // When we translate a function, we need to map its incoming arguments to the
1587 // spaces that have been created for them (by code in the llallocas field of
1588 // the function's fn_ctxt).  create_llargs_for_fn_args populates the llargs
1589 // field of the fn_ctxt with
1590 fn create_llargs_for_fn_args(cx: fn_ctxt,
1591                              ty_self: self_arg,
1592                              args: ~[ast::arg]) -> ~[ValueRef] {
1593     let _icx = cx.insn_ctxt("create_llargs_for_fn_args");
1594
1595     match ty_self {
1596       impl_self(tt) => {
1597         cx.llself = Some(ValSelfData {
1598             v: cx.llenv,
1599             t: tt,
1600             is_owned: false
1601         });
1602       }
1603       impl_owned_self(tt) => {
1604         cx.llself = Some(ValSelfData {
1605             v: cx.llenv,
1606             t: tt,
1607             is_owned: true
1608         });
1609       }
1610       no_self => ()
1611     }
1612
1613     // Return an array containing the ValueRefs that we get from
1614     // llvm::LLVMGetParam for each argument.
1615     vec::from_fn(args.len(), |i| {
1616         unsafe {
1617             let arg_n = first_real_arg + i;
1618             llvm::LLVMGetParam(cx.llfn, arg_n as c_uint)
1619         }
1620     })
1621 }
1622
1623 fn copy_args_to_allocas(fcx: fn_ctxt,
1624                         bcx: block,
1625                         args: &[ast::arg],
1626                         raw_llargs: &[ValueRef],
1627                         arg_tys: &[ty::arg]) -> block {
1628     let _icx = fcx.insn_ctxt("copy_args_to_allocas");
1629     let tcx = bcx.tcx();
1630     let mut bcx = bcx;
1631
1632     match fcx.llself {
1633       Some(copy slf) => {
1634         // We really should do this regardless of whether self is owned, but
1635         // it doesn't work right with default method impls yet. (FIXME: #2794)
1636         if slf.is_owned {
1637             let self_val = PointerCast(bcx, slf.v,
1638                                        T_ptr(type_of(bcx.ccx(), slf.t)));
1639             fcx.llself = Some(ValSelfData {v: self_val, ..slf});
1640             add_clean(bcx, self_val, slf.t);
1641         }
1642       }
1643       _ => {}
1644     }
1645
1646     for uint::range(0, arg_tys.len()) |arg_n| {
1647         let arg_ty = &arg_tys[arg_n];
1648         let raw_llarg = raw_llargs[arg_n];
1649         let arg_id = args[arg_n].id;
1650
1651         // For certain mode/type combinations, the raw llarg values are passed
1652         // by value.  However, within the fn body itself, we want to always
1653         // have all locals and arguments be by-ref so that we can cancel the
1654         // cleanup and for better interaction with LLVM's debug info.  So, if
1655         // the argument would be passed by value, we store it into an alloca.
1656         // This alloca should be optimized away by LLVM's mem-to-reg pass in
1657         // the event it's not truly needed.
1658         let llarg;
1659         match ty::resolved_mode(tcx, arg_ty.mode) {
1660             ast::by_ref => {
1661                 llarg = raw_llarg;
1662             }
1663             ast::by_move | ast::by_copy => {
1664                 // only by value if immediate:
1665                 if datum::appropriate_mode(arg_ty.ty).is_by_value() {
1666                     let alloc = alloc_ty(bcx, arg_ty.ty);
1667                     Store(bcx, raw_llarg, alloc);
1668                     llarg = alloc;
1669                 } else {
1670                     llarg = raw_llarg;
1671                 }
1672
1673                 add_clean(bcx, llarg, arg_ty.ty);
1674             }
1675             ast::by_val => {
1676                 // always by value, also not owned, so don't add a cleanup:
1677                 let alloc = alloc_ty(bcx, arg_ty.ty);
1678                 Store(bcx, raw_llarg, alloc);
1679                 llarg = alloc;
1680             }
1681         }
1682
1683         bcx = _match::bind_irrefutable_pat(bcx,
1684                                           args[arg_n].pat,
1685                                           llarg,
1686                                           false,
1687                                           _match::BindArgument);
1688
1689         fcx.llargs.insert(arg_id, local_mem(llarg));
1690
1691         if fcx.ccx.sess.opts.extra_debuginfo {
1692             debuginfo::create_arg(bcx, args[arg_n], args[arg_n].ty.span);
1693         }
1694     }
1695
1696     return bcx;
1697 }
1698
1699 // Ties up the llstaticallocas -> llloadenv -> lltop edges,
1700 // and builds the return block.
1701 fn finish_fn(fcx: fn_ctxt, lltop: BasicBlockRef) {
1702     let _icx = fcx.insn_ctxt("finish_fn");
1703     tie_up_header_blocks(fcx, lltop);
1704     let ret_cx = raw_block(fcx, false, fcx.llreturn);
1705     RetVoid(ret_cx);
1706 }
1707
1708 fn tie_up_header_blocks(fcx: fn_ctxt, lltop: BasicBlockRef) {
1709     let _icx = fcx.insn_ctxt("tie_up_header_blocks");
1710     match fcx.llloadenv {
1711         Some(copy ll) => {
1712             Br(raw_block(fcx, false, fcx.llstaticallocas), ll);
1713             Br(raw_block(fcx, false, ll), lltop);
1714         }
1715         None => {
1716             Br(raw_block(fcx, false, fcx.llstaticallocas), lltop);
1717         }
1718     }
1719 }
1720
1721 enum self_arg { impl_self(ty::t), impl_owned_self(ty::t), no_self, }
1722
1723 // trans_closure: Builds an LLVM function out of a source function.
1724 // If the function closes over its environment a closure will be
1725 // returned.
1726 fn trans_closure(ccx: @crate_ctxt,
1727                  +path: path,
1728                  decl: ast::fn_decl,
1729                  body: ast::blk,
1730                  llfndecl: ValueRef,
1731                  ty_self: self_arg,
1732                  +param_substs: Option<param_substs>,
1733                  id: ast::node_id,
1734                  impl_id: Option<ast::def_id>,
1735                  maybe_load_env: fn(fn_ctxt),
1736                  finish: fn(block)) {
1737     ccx.stats.n_closures += 1;
1738     let _icx = ccx.insn_ctxt("trans_closure");
1739     set_uwtable(llfndecl);
1740
1741     // Set up arguments to the function.
1742     let fcx = new_fn_ctxt_w_id(ccx, path, llfndecl, id, impl_id, param_substs,
1743                                   Some(body.span));
1744     let raw_llargs = create_llargs_for_fn_args(fcx, ty_self,
1745                                                /*bad*/copy decl.inputs);
1746
1747     // Set GC for function.
1748     if ccx.sess.opts.gc {
1749         do str::as_c_str("generic") |strategy| {
1750             unsafe {
1751                 llvm::LLVMSetGC(fcx.llfn, strategy);
1752             }
1753         }
1754         ccx.uses_gc = true;
1755     }
1756
1757     // Create the first basic block in the function and keep a handle on it to
1758     //  pass to finish_fn later.
1759     let bcx_top = top_scope_block(fcx, body.info());
1760     let mut bcx = bcx_top;
1761     let lltop = bcx.llbb;
1762     let block_ty = node_id_type(bcx, body.node.id);
1763
1764     let arg_tys = ty::ty_fn_args(node_id_type(bcx, id));
1765     bcx = copy_args_to_allocas(fcx, bcx, decl.inputs, raw_llargs, arg_tys);
1766
1767     maybe_load_env(fcx);
1768
1769     // This call to trans_block is the place where we bridge between
1770     // translation calls that don't have a return value (trans_crate,
1771     // trans_mod, trans_item, et cetera) and those that do
1772     // (trans_block, trans_expr, et cetera).
1773     if body.node.expr.is_none() || ty::type_is_bot(block_ty) ||
1774         ty::type_is_nil(block_ty)
1775     {
1776         bcx = controlflow::trans_block(bcx, body, expr::Ignore);
1777     } else {
1778         bcx = controlflow::trans_block(bcx, body, expr::SaveIn(fcx.llretptr));
1779     }
1780
1781     finish(bcx);
1782     cleanup_and_Br(bcx, bcx_top, fcx.llreturn);
1783
1784     // Insert the mandatory first few basic blocks before lltop.
1785     finish_fn(fcx, lltop);
1786 }
1787
1788 // trans_fn: creates an LLVM function corresponding to a source language
1789 // function.
1790 fn trans_fn(ccx: @crate_ctxt,
1791             +path: path,
1792             decl: ast::fn_decl,
1793             body: ast::blk,
1794             llfndecl: ValueRef,
1795             ty_self: self_arg,
1796             +param_substs: Option<param_substs>,
1797             id: ast::node_id,
1798             impl_id: Option<ast::def_id>) {
1799     let do_time = ccx.sess.trans_stats();
1800     let start = if do_time { time::get_time() }
1801                 else { time::Timespec::new(0, 0) };
1802     debug!("trans_fn(ty_self=%?)", ty_self);
1803     let _icx = ccx.insn_ctxt("trans_fn");
1804     ccx.stats.n_fns += 1;
1805     // XXX: Bad copy of `path`.
1806     trans_closure(ccx, copy path, decl, body, llfndecl, ty_self,
1807                   param_substs, id, impl_id,
1808                   |fcx| {
1809                       if ccx.sess.opts.extra_debuginfo {
1810                           debuginfo::create_function(fcx);
1811                       }
1812                   },
1813                   |_bcx| { });
1814     if do_time {
1815         let end = time::get_time();
1816         log_fn_time(ccx, path_str(ccx.sess, path), start, end);
1817     }
1818 }
1819
1820 fn trans_enum_variant(ccx: @crate_ctxt,
1821                       enum_id: ast::node_id,
1822                       variant: ast::variant,
1823                       args: ~[ast::variant_arg],
1824                       disr: int,
1825                       is_degen: bool,
1826                       +param_substs: Option<param_substs>,
1827                       llfndecl: ValueRef) {
1828     let _icx = ccx.insn_ctxt("trans_enum_variant");
1829     // Translate variant arguments to function arguments.
1830     let fn_args = vec::map(args, |varg|
1831         {mode: ast::expl(ast::by_copy),
1832          ty: varg.ty,
1833          pat: ast_util::ident_to_pat(ccx.tcx.sess.next_node_id(),
1834                                      ast_util::dummy_sp(),
1835                                      special_idents::arg),
1836          id: varg.id});
1837     // XXX: Bad copy of `param_substs`.
1838     let fcx = new_fn_ctxt_w_id(ccx, ~[], llfndecl, variant.node.id, None,
1839                                copy param_substs, None);
1840     // XXX: Bad copy.
1841     let raw_llargs = create_llargs_for_fn_args(fcx, no_self, copy fn_args);
1842     let ty_param_substs = match param_substs {
1843       Some(ref substs) => /*bad*/copy substs.tys,
1844       None => ~[]
1845     };
1846     let bcx = top_scope_block(fcx, None), lltop = bcx.llbb;
1847     let arg_tys = ty::ty_fn_args(node_id_type(bcx, variant.node.id));
1848     let bcx = copy_args_to_allocas(fcx, bcx, fn_args, raw_llargs, arg_tys);
1849
1850     // Cast the enum to a type we can GEP into.
1851     let llblobptr = if is_degen {
1852         fcx.llretptr
1853     } else {
1854         let llenumptr =
1855             PointerCast(bcx, fcx.llretptr, T_opaque_enum_ptr(ccx));
1856         let lldiscrimptr = GEPi(bcx, llenumptr, [0u, 0u]);
1857         Store(bcx, C_int(ccx, disr), lldiscrimptr);
1858         GEPi(bcx, llenumptr, [0u, 1u])
1859     };
1860     let t_id = local_def(enum_id);
1861     let v_id = local_def(variant.node.id);
1862     for vec::eachi(args) |i, va| {
1863         let lldestptr = GEP_enum(bcx, llblobptr, t_id, v_id,
1864                                  /*bad*/copy ty_param_substs, i);
1865         // If this argument to this function is a enum, it'll have come in to
1866         // this function as an opaque blob due to the way that type_of()
1867         // works. So we have to cast to the destination's view of the type.
1868         let llarg = match fcx.llargs.find(va.id) {
1869             Some(local_mem(x)) => x,
1870             _ => fail ~"trans_enum_variant: how do we know this works?",
1871         };
1872         let arg_ty = arg_tys[i].ty;
1873         memcpy_ty(bcx, lldestptr, llarg, arg_ty);
1874     }
1875     build_return(bcx);
1876     finish_fn(fcx, lltop);
1877 }
1878
1879 // NB: In theory this should be merged with the function above. But the AST
1880 // structures are completely different, so very little code would be shared.
1881 fn trans_tuple_struct(ccx: @crate_ctxt,
1882                       fields: ~[@ast::struct_field],
1883                       ctor_id: ast::node_id,
1884                       +param_substs: Option<param_substs>,
1885                       llfndecl: ValueRef) {
1886     let _icx = ccx.insn_ctxt("trans_tuple_struct");
1887
1888     // Translate struct fields to function arguments.
1889     let fn_args = do fields.map |field| {
1890         {
1891             mode: ast::expl(ast::by_copy),
1892             ty: field.node.ty,
1893             pat: ast_util::ident_to_pat(ccx.tcx.sess.next_node_id(),
1894                                         ast_util::dummy_sp(),
1895                                         special_idents::arg),
1896             id: field.node.id
1897         }
1898     };
1899
1900     let fcx = new_fn_ctxt_w_id(ccx, ~[], llfndecl, ctor_id, None,
1901                                param_substs, None);
1902
1903     // XXX: Bad copy.
1904     let raw_llargs = create_llargs_for_fn_args(fcx, no_self, copy fn_args);
1905
1906     let bcx = top_scope_block(fcx, None);
1907     let lltop = bcx.llbb;
1908     let arg_tys = ty::ty_fn_args(node_id_type(bcx, ctor_id));
1909     let bcx = copy_args_to_allocas(fcx, bcx, fn_args, raw_llargs, arg_tys);
1910
1911     for fields.eachi |i, field| {
1912         let lldestptr = GEPi(bcx, fcx.llretptr, [0, 0, i]);
1913         let llarg = match fcx.llargs.get(field.node.id) {
1914             local_mem(x) => x,
1915             _ => {
1916                 ccx.tcx.sess.bug(~"trans_tuple_struct: llarg wasn't \
1917                                    local_mem")
1918             }
1919         };
1920         let arg_ty = arg_tys[i].ty;
1921         memcpy_ty(bcx, lldestptr, llarg, arg_ty);
1922     }
1923
1924     build_return(bcx);
1925     finish_fn(fcx, lltop);
1926 }
1927
1928 fn trans_struct_dtor(ccx: @crate_ctxt,
1929                      +path: path,
1930                      body: ast::blk,
1931                      dtor_id: ast::node_id,
1932                      +psubsts: Option<param_substs>,
1933                      hash_id: Option<mono_id>,
1934                      parent_id: ast::def_id)
1935                   -> ValueRef {
1936   let tcx = ccx.tcx;
1937   /* Look up the parent class's def_id */
1938   let mut class_ty = ty::lookup_item_type(tcx, parent_id).ty;
1939   /* Substitute in the class type if necessary */
1940     do option::iter(&psubsts) |ss| {
1941     class_ty = ty::subst_tps(tcx, ss.tys, ss.self_ty, class_ty);
1942   }
1943
1944   /* The dtor takes a (null) output pointer, and a self argument,
1945      and returns () */
1946   let lldty = type_of_dtor(ccx, class_ty);
1947
1948   // XXX: Bad copies.
1949   let s = get_dtor_symbol(ccx, copy path, dtor_id, copy psubsts);
1950
1951   /* Register the dtor as a function. It has external linkage */
1952   let lldecl = decl_internal_cdecl_fn(ccx.llmod, s, lldty);
1953   lib::llvm::SetLinkage(lldecl, lib::llvm::ExternalLinkage);
1954
1955   /* If we're monomorphizing, register the monomorphized decl
1956      for the dtor */
1957     do option::iter(&hash_id) |h_id| {
1958     ccx.monomorphized.insert(*h_id, lldecl);
1959   }
1960   /* Translate the dtor body */
1961   trans_fn(ccx, path, ast_util::dtor_dec(),
1962            body, lldecl, impl_self(class_ty), psubsts, dtor_id, None);
1963   lldecl
1964 }
1965
1966 fn trans_enum_def(ccx: @crate_ctxt, enum_definition: ast::enum_def,
1967                   id: ast::node_id, tps: ~[ast::ty_param], degen: bool,
1968                   path: @ast_map::path, vi: @~[ty::VariantInfo],
1969                   i: &mut uint) {
1970     for vec::each(enum_definition.variants) |variant| {
1971         let disr_val = vi[*i].disr_val;
1972         *i += 1;
1973
1974         match variant.node.kind {
1975             ast::tuple_variant_kind(ref args) if args.len() > 0 => {
1976                 let llfn = get_item_val(ccx, variant.node.id);
1977                 trans_enum_variant(ccx, id, *variant, /*bad*/copy *args,
1978                                    disr_val, degen, None, llfn);
1979             }
1980             ast::tuple_variant_kind(_) => {
1981                 // Nothing to do.
1982             }
1983             ast::struct_variant_kind(struct_def) => {
1984                 trans_struct_def(ccx, struct_def, /*bad*/copy tps, path,
1985                                  variant.node.id);
1986             }
1987             ast::enum_variant_kind(ref enum_definition) => {
1988                 trans_enum_def(ccx,
1989                                *enum_definition,
1990                                id,
1991                                /*bad*/copy tps,
1992                                degen,
1993                                path,
1994                                vi,
1995                                i);
1996             }
1997         }
1998     }
1999 }
2000
2001 fn trans_item(ccx: @crate_ctxt, item: ast::item) {
2002     let _icx = ccx.insn_ctxt("trans_item");
2003     let path = match ccx.tcx.items.get(item.id) {
2004         ast_map::node_item(_, p) => p,
2005         // tjc: ?
2006         _ => fail ~"trans_item",
2007     };
2008     match /*bad*/copy item.node {
2009       // XXX: Bad copies.
2010       ast::item_fn(copy decl, purity, copy tps, ref body) => {
2011         if purity == ast::extern_fn  {
2012             let llfndecl = get_item_val(ccx, item.id);
2013             foreign::trans_foreign_fn(ccx,
2014                                      vec::append(
2015                                          /*bad*/copy *path,
2016                                          ~[path_name(item.ident)]),
2017                                      decl, (*body), llfndecl, item.id);
2018         } else if tps.is_empty() {
2019             let llfndecl = get_item_val(ccx, item.id);
2020             trans_fn(ccx,
2021                      vec::append(/*bad*/copy *path, ~[path_name(item.ident)]),
2022                      decl, (*body), llfndecl, no_self, None, item.id, None);
2023         } else {
2024             for vec::each((*body).node.stmts) |stmt| {
2025                 match stmt.node {
2026                   ast::stmt_decl(@ast::spanned { node: ast::decl_item(i),
2027                                                  _ }, _) => {
2028                     trans_item(ccx, *i);
2029                   }
2030                   _ => ()
2031                 }
2032             }
2033         }
2034       }
2035       ast::item_impl(tps, _, _, ms) => {
2036         meth::trans_impl(ccx, /*bad*/copy *path, item.ident, ms, tps, None,
2037                          item.id);
2038       }
2039       ast::item_mod(m) => {
2040         trans_mod(ccx, m);
2041       }
2042       ast::item_enum(ref enum_definition, ref tps) => {
2043         if tps.len() == 0u {
2044             let degen = (*enum_definition).variants.len() == 1u;
2045             let vi = ty::enum_variants(ccx.tcx, local_def(item.id));
2046             let mut i = 0;
2047             trans_enum_def(ccx, (*enum_definition), item.id, /*bad*/copy *tps,
2048                            degen, path, vi, &mut i);
2049         }
2050       }
2051       ast::item_const(_, expr) => consts::trans_const(ccx, expr, item.id),
2052       ast::item_foreign_mod(foreign_mod) => {
2053         let abi = match attr::foreign_abi(item.attrs) {
2054           either::Right(abi_) => abi_,
2055           either::Left(ref msg) => ccx.sess.span_fatal(item.span,
2056                                                        /*bad*/copy *msg)
2057         };
2058         foreign::trans_foreign_mod(ccx, foreign_mod, abi);
2059       }
2060       ast::item_struct(struct_def, tps) => {
2061         trans_struct_def(ccx, struct_def, tps, path, item.id);
2062       }
2063       _ => {/* fall through */ }
2064     }
2065 }
2066
2067 fn trans_struct_def(ccx: @crate_ctxt, struct_def: @ast::struct_def,
2068                     tps: ~[ast::ty_param], path: @ast_map::path,
2069                     id: ast::node_id) {
2070     // If there are type parameters, the destructor and constructor will be
2071     // monomorphized, so we don't translate them here.
2072     if tps.len() == 0u {
2073         // Translate the destructor.
2074         do option::iter(&struct_def.dtor) |dtor| {
2075             trans_struct_dtor(ccx, /*bad*/copy *path, dtor.node.body,
2076                              dtor.node.id, None, None, local_def(id));
2077         };
2078
2079         // If this is a tuple-like struct, translate the constructor.
2080         match struct_def.ctor_id {
2081             // We only need to translate a constructor if there are fields;
2082             // otherwise this is a unit-like struct.
2083             Some(ctor_id) if struct_def.fields.len() > 0 => {
2084                 let llfndecl = get_item_val(ccx, ctor_id);
2085                 trans_tuple_struct(ccx, /*bad*/copy struct_def.fields,
2086                                    ctor_id, None, llfndecl);
2087             }
2088             Some(_) | None => {}
2089         }
2090     }
2091 }
2092
2093 // Translate a module. Doing this amounts to translating the items in the
2094 // module; there ends up being no artifact (aside from linkage names) of
2095 // separate modules in the compiled program.  That's because modules exist
2096 // only as a convenience for humans working with the code, to organize names
2097 // and control visibility.
2098 fn trans_mod(ccx: @crate_ctxt, m: ast::_mod) {
2099     let _icx = ccx.insn_ctxt("trans_mod");
2100     for vec::each(m.items) |item| {
2101         trans_item(ccx, **item);
2102     }
2103 }
2104
2105 fn get_pair_fn_ty(llpairty: TypeRef) -> TypeRef {
2106     // Bit of a kludge: pick the fn typeref out of the pair.
2107     return struct_elt(llpairty, 0u);
2108 }
2109
2110 fn register_fn(ccx: @crate_ctxt,
2111                sp: span,
2112                +path: path,
2113                node_id: ast::node_id,
2114                attrs: &[ast::attribute])
2115             -> ValueRef {
2116     let t = ty::node_id_to_type(ccx.tcx, node_id);
2117     register_fn_full(ccx, sp, path, node_id, attrs, t)
2118 }
2119
2120 fn register_fn_full(ccx: @crate_ctxt,
2121                     sp: span,
2122                     +path: path,
2123                     node_id: ast::node_id,
2124                     attrs: &[ast::attribute],
2125                     node_type: ty::t)
2126                  -> ValueRef {
2127     let llfty = type_of_fn_from_ty(ccx, node_type);
2128     register_fn_fuller(ccx, sp, path, node_id, attrs, node_type,
2129                        lib::llvm::CCallConv, llfty)
2130 }
2131
2132 fn register_fn_fuller(ccx: @crate_ctxt,
2133                       sp: span,
2134                       +path: path,
2135                       node_id: ast::node_id,
2136                       attrs: &[ast::attribute],
2137                       node_type: ty::t,
2138                       cc: lib::llvm::CallConv,
2139                       llfty: TypeRef)
2140                    -> ValueRef {
2141     debug!("register_fn_fuller creating fn for item %d with path %s",
2142            node_id,
2143            ast_map::path_to_str(path, ccx.sess.parse_sess.interner));
2144
2145     let ps = if attr::attrs_contains_name(attrs, "no_mangle") {
2146         path_elt_to_str(path.last(), ccx.sess.parse_sess.interner)
2147     } else {
2148         mangle_exported_name(ccx, /*bad*/copy path, node_type)
2149     };
2150
2151     // XXX: Bad copy.
2152     let llfn: ValueRef = decl_fn(ccx.llmod, copy ps, cc, llfty);
2153     ccx.item_symbols.insert(node_id, ps);
2154
2155     let is_main = is_main_name(path) && !ccx.sess.building_library;
2156     if is_main { create_main_wrapper(ccx, sp, llfn); }
2157     llfn
2158 }
2159
2160 // Create a _rust_main(args: ~[str]) function which will be called from the
2161 // runtime rust_start function
2162 fn create_main_wrapper(ccx: @crate_ctxt, sp: span, main_llfn: ValueRef) {
2163
2164     if ccx.main_fn != None::<ValueRef> {
2165         ccx.sess.span_fatal(sp, ~"multiple 'main' functions");
2166     }
2167
2168     let llfn = create_main(ccx, main_llfn);
2169     ccx.main_fn = Some(llfn);
2170     create_entry_fn(ccx, llfn);
2171
2172     fn create_main(ccx: @crate_ctxt, main_llfn: ValueRef) -> ValueRef {
2173         let unit_ty = ty::mk_estr(ccx.tcx, ty::vstore_uniq);
2174         let vecarg_ty: ty::arg =
2175             {mode: ast::expl(ast::by_val),
2176              ty: ty::mk_evec(ccx.tcx, {ty: unit_ty, mutbl: ast::m_imm},
2177                              ty::vstore_uniq)};
2178         let nt = ty::mk_nil(ccx.tcx);
2179         let llfty = type_of_fn(ccx, ~[vecarg_ty], nt);
2180         let llfdecl = decl_fn(ccx.llmod, ~"_rust_main",
2181                               lib::llvm::CCallConv, llfty);
2182
2183         let fcx = new_fn_ctxt(ccx, ~[], llfdecl, None);
2184
2185         let bcx = top_scope_block(fcx, None);
2186         let lltop = bcx.llbb;
2187
2188         // Call main.
2189         let lloutputarg = unsafe { llvm::LLVMGetParam(llfdecl, 0 as c_uint) };
2190         let llenvarg = unsafe { llvm::LLVMGetParam(llfdecl, 1 as c_uint) };
2191         let mut args = ~[lloutputarg, llenvarg];
2192         Call(bcx, main_llfn, args);
2193
2194         build_return(bcx);
2195         finish_fn(fcx, lltop);
2196         return llfdecl;
2197     }
2198
2199     fn create_entry_fn(ccx: @crate_ctxt, rust_main: ValueRef) {
2200         #[cfg(windows)]
2201         fn main_name() -> ~str { return ~"WinMain@16"; }
2202         #[cfg(unix)]
2203         fn main_name() -> ~str { return ~"main"; }
2204         let llfty = T_fn(~[ccx.int_type, ccx.int_type], ccx.int_type);
2205         let llfn = decl_cdecl_fn(ccx.llmod, main_name(), llfty);
2206         let llbb = str::as_c_str(~"top", |buf| {
2207             unsafe {
2208                 llvm::LLVMAppendBasicBlock(llfn, buf)
2209             }
2210         });
2211         let bld = ccx.builder.B;
2212         unsafe {
2213             llvm::LLVMPositionBuilderAtEnd(bld, llbb);
2214         }
2215         let crate_map = ccx.crate_map;
2216         let start_ty = T_fn(~[val_ty(rust_main), ccx.int_type, ccx.int_type,
2217                              val_ty(crate_map)], ccx.int_type);
2218         let start = decl_cdecl_fn(ccx.llmod, ~"rust_start", start_ty);
2219
2220         let args = unsafe {
2221             ~[
2222                 rust_main,
2223                 llvm::LLVMGetParam(llfn, 0 as c_uint),
2224                 llvm::LLVMGetParam(llfn, 1 as c_uint),
2225                 crate_map
2226             ]
2227         };
2228         let result = unsafe {
2229             llvm::LLVMBuildCall(bld, start, vec::raw::to_ptr(args),
2230                                 args.len() as c_uint, noname())
2231         };
2232         unsafe {
2233             llvm::LLVMBuildRet(bld, result);
2234         }
2235     }
2236 }
2237
2238 fn fill_fn_pair(bcx: block, pair: ValueRef, llfn: ValueRef,
2239                 llenvptr: ValueRef) {
2240     let ccx = bcx.ccx();
2241     let code_cell = GEPi(bcx, pair, [0u, abi::fn_field_code]);
2242     Store(bcx, llfn, code_cell);
2243     let env_cell = GEPi(bcx, pair, [0u, abi::fn_field_box]);
2244     let llenvblobptr = PointerCast(bcx, llenvptr, T_opaque_box_ptr(ccx));
2245     Store(bcx, llenvblobptr, env_cell);
2246 }
2247
2248 fn item_path(ccx: @crate_ctxt, i: @ast::item) -> path {
2249     vec::append(
2250         /*bad*/copy *match ccx.tcx.items.get(i.id) {
2251             ast_map::node_item(_, p) => p,
2252                 // separate map for paths?
2253             _ => fail ~"item_path"
2254         },
2255         ~[path_name(i.ident)])
2256 }
2257
2258 /* If there's already a symbol for the dtor with <id> and substs <substs>,
2259    return it; otherwise, create one and register it, returning it as well */
2260 fn get_dtor_symbol(ccx: @crate_ctxt,
2261                    +path: path,
2262                    id: ast::node_id,
2263                    +substs: Option<param_substs>)
2264                 -> ~str {
2265   let t = ty::node_id_to_type(ccx.tcx, id);
2266   match ccx.item_symbols.find(id) {
2267      Some(ref s) => (/*bad*/copy *s),
2268      None if substs.is_none() => {
2269        let s = mangle_exported_name(
2270            ccx,
2271            vec::append(path, ~[path_name((ccx.names)(~"dtor"))]),
2272            t);
2273        // XXX: Bad copy, use `@str`?
2274        ccx.item_symbols.insert(id, copy s);
2275        s
2276      }
2277      None   => {
2278        // Monomorphizing, so just make a symbol, don't add
2279        // this to item_symbols
2280        match substs {
2281          Some(ss) => {
2282            let mono_ty = ty::subst_tps(ccx.tcx, ss.tys, ss.self_ty, t);
2283            mangle_exported_name(
2284                ccx,
2285                vec::append(path,
2286                            ~[path_name((ccx.names)(~"dtor"))]),
2287                mono_ty)
2288          }
2289          None => {
2290              ccx.sess.bug(fmt!("get_dtor_symbol: not monomorphizing and \
2291                couldn't find a symbol for dtor %?", path));
2292          }
2293        }
2294      }
2295   }
2296 }
2297
2298 fn get_item_val(ccx: @crate_ctxt, id: ast::node_id) -> ValueRef {
2299     debug!("get_item_val(id=`%?`)", id);
2300     let tcx = ccx.tcx;
2301     match ccx.item_vals.find(id) {
2302       Some(v) => v,
2303       None => {
2304
2305         let mut exprt = false;
2306         let val = match ccx.tcx.items.get(id) {
2307           ast_map::node_item(i, pth) => {
2308             let my_path = vec::append(/*bad*/copy *pth,
2309                                       ~[path_name(i.ident)]);
2310             match i.node {
2311               ast::item_const(_, expr) => {
2312                 let typ = ty::node_id_to_type(ccx.tcx, i.id);
2313                 let s = mangle_exported_name(ccx, my_path, typ);
2314                 // We need the translated value here, because for enums the
2315                 // LLVM type is not fully determined by the Rust type.
2316                 let v = consts::const_expr(ccx, expr);
2317                 ccx.const_values.insert(id, v);
2318                 unsafe {
2319                     let llty = llvm::LLVMTypeOf(v);
2320                     let g = str::as_c_str(s, |buf| {
2321                         llvm::LLVMAddGlobal(ccx.llmod, llty, buf)
2322                     });
2323                     ccx.item_symbols.insert(i.id, s);
2324                     g
2325                 }
2326               }
2327               ast::item_fn(_, purity, _, _) => {
2328                 let llfn = if purity != ast::extern_fn {
2329                     register_fn(ccx, i.span, my_path, i.id, i.attrs)
2330                 } else {
2331                     foreign::register_foreign_fn(ccx,
2332                                                  i.span,
2333                                                  my_path,
2334                                                  i.id,
2335                                                  i.attrs)
2336                 };
2337                 set_inline_hint_if_appr(/*bad*/copy i.attrs, llfn);
2338                 llfn
2339               }
2340               _ => fail ~"get_item_val: weird result in table"
2341             }
2342           }
2343           ast_map::node_trait_method(trait_method, _, pth) => {
2344             debug!("get_item_val(): processing a node_trait_method");
2345             match *trait_method {
2346               ast::required(_) => {
2347                 ccx.sess.bug(~"unexpected variant: required trait method in \
2348                                get_item_val()");
2349               }
2350               ast::provided(m) => {
2351                 exprt = true;
2352                 register_method(ccx, id, pth, m)
2353               }
2354             }
2355           }
2356           ast_map::node_method(m, _, pth) => {
2357             exprt = true;
2358             register_method(ccx, id, pth, m)
2359           }
2360           ast_map::node_foreign_item(ni, _, pth) => {
2361             exprt = true;
2362             match ni.node {
2363                 ast::foreign_item_fn(*) => {
2364                     register_fn(ccx, ni.span,
2365                                 vec::append(/*bad*/copy *pth,
2366                                             ~[path_name(ni.ident)]),
2367                                 ni.id,
2368                                 ni.attrs)
2369                 }
2370                 ast::foreign_item_const(*) => {
2371                     let typ = ty::node_id_to_type(ccx.tcx, ni.id);
2372                     let ident = ccx.sess.parse_sess.interner.get(ni.ident);
2373                     let g = do str::as_c_str(*ident) |buf| {
2374                         unsafe {
2375                             llvm::LLVMAddGlobal(ccx.llmod,
2376                                                 type_of(ccx, typ),
2377                                                 buf)
2378                         }
2379                     };
2380                     g
2381                 }
2382             }
2383           }
2384           ast_map::node_dtor(_, dt, parent_id, pt) => {
2385             /*
2386                 Don't just call register_fn, since we don't want to add
2387                 the implicit self argument automatically (we want to make sure
2388                 it has the right type)
2389             */
2390             // Want parent_id and not id, because id is the dtor's type
2391             let class_ty = ty::lookup_item_type(tcx, parent_id).ty;
2392             // This code shouldn't be reached if the class is generic
2393             assert !ty::type_has_params(class_ty);
2394             let lldty = unsafe {
2395                 T_fn(~[
2396                     T_ptr(type_of(ccx, ty::mk_nil(tcx))),
2397                     T_ptr(type_of(ccx, class_ty))
2398                 ],
2399                 llvm::LLVMVoidType())
2400             };
2401             let s = get_dtor_symbol(ccx, /*bad*/copy *pt, dt.node.id, None);
2402
2403             /* Make the declaration for the dtor */
2404             let llfn = decl_internal_cdecl_fn(ccx.llmod, s, lldty);
2405             lib::llvm::SetLinkage(llfn, lib::llvm::ExternalLinkage);
2406             llfn
2407           }
2408
2409           ast_map::node_variant(ref v, enm, pth) => {
2410             let llfn;
2411             match /*bad*/copy (*v).node.kind {
2412                 ast::tuple_variant_kind(args) => {
2413                     assert args.len() != 0u;
2414                     let pth = vec::append(/*bad*/copy *pth,
2415                                           ~[path_name(enm.ident),
2416                                             path_name((*v).node.name)]);
2417                     llfn = match enm.node {
2418                       ast::item_enum(_, _) => {
2419                         register_fn(ccx, (*v).span, pth, id, enm.attrs)
2420                       }
2421                       _ => fail ~"node_variant, shouldn't happen"
2422                     };
2423                 }
2424                 ast::struct_variant_kind(_) => {
2425                     fail ~"struct variant kind unexpected in get_item_val"
2426                 }
2427                 ast::enum_variant_kind(_) => {
2428                     fail ~"enum variant kind unexpected in get_item_val"
2429                 }
2430             }
2431             set_inline_hint(llfn);
2432             llfn
2433           }
2434
2435           ast_map::node_struct_ctor(struct_def, struct_item, struct_path) => {
2436             // Only register the constructor if this is a tuple-like struct.
2437             match struct_def.ctor_id {
2438                 None => {
2439                     ccx.tcx.sess.bug(~"attempt to register a constructor of \
2440                                        a non-tuple-like struct")
2441                 }
2442                 Some(ctor_id) => {
2443                     let llfn = register_fn(ccx,
2444                                            struct_item.span,
2445                                            /*bad*/copy *struct_path,
2446                                            ctor_id,
2447                                            struct_item.attrs);
2448                     set_inline_hint(llfn);
2449                     llfn
2450                 }
2451             }
2452           }
2453
2454           _ => {
2455             ccx.sess.bug(~"get_item_val(): unexpected variant")
2456           }
2457         };
2458         if !(exprt || ccx.reachable.contains_key(id)) {
2459             lib::llvm::SetLinkage(val, lib::llvm::InternalLinkage);
2460         }
2461         ccx.item_vals.insert(id, val);
2462         val
2463       }
2464     }
2465 }
2466
2467 fn register_method(ccx: @crate_ctxt, id: ast::node_id, pth: @ast_map::path,
2468                 m: @ast::method) -> ValueRef {
2469     let mty = ty::node_id_to_type(ccx.tcx, id);
2470     let pth = vec::append(/*bad*/copy *pth, ~[path_name((ccx.names)(~"meth")),
2471                                   path_name(m.ident)]);
2472     let llfn = register_fn_full(ccx, m.span, pth, id, m.attrs, mty);
2473     set_inline_hint_if_appr(/*bad*/copy m.attrs, llfn);
2474     llfn
2475 }
2476
2477 // The constant translation pass.
2478 fn trans_constant(ccx: @crate_ctxt, it: @ast::item) {
2479     let _icx = ccx.insn_ctxt("trans_constant");
2480     match it.node {
2481       ast::item_enum(ref enum_definition, _) => {
2482         let vi = ty::enum_variants(ccx.tcx, {crate: ast::local_crate,
2483                                              node: it.id});
2484         let mut i = 0;
2485         let path = item_path(ccx, it);
2486         for vec::each((*enum_definition).variants) |variant| {
2487             let p = vec::append(/*bad*/copy path, ~[
2488                 path_name(variant.node.name),
2489                 path_name(special_idents::descrim)
2490             ]);
2491             let s = mangle_exported_name(ccx, p, ty::mk_int(ccx.tcx));
2492             let disr_val = vi[i].disr_val;
2493             // XXX: Bad copy.
2494             note_unique_llvm_symbol(ccx, copy s);
2495             let discrim_gvar = str::as_c_str(s, |buf| {
2496                 unsafe {
2497                     llvm::LLVMAddGlobal(ccx.llmod, ccx.int_type, buf)
2498                 }
2499             });
2500             unsafe {
2501                 llvm::LLVMSetInitializer(discrim_gvar, C_int(ccx, disr_val));
2502                 llvm::LLVMSetGlobalConstant(discrim_gvar, True);
2503             }
2504             ccx.discrims.insert(
2505                 local_def(variant.node.id), discrim_gvar);
2506             ccx.discrim_symbols.insert(variant.node.id, s);
2507             i += 1;
2508         }
2509       }
2510       _ => ()
2511     }
2512 }
2513
2514 fn trans_constants(ccx: @crate_ctxt, crate: @ast::crate) {
2515     visit::visit_crate(
2516         *crate, (),
2517         visit::mk_simple_visitor(@visit::SimpleVisitor {
2518             visit_item: |a| trans_constant(ccx, a),
2519             ..*visit::default_simple_visitor()
2520         }));
2521 }
2522
2523 fn vp2i(cx: block, v: ValueRef) -> ValueRef {
2524     let ccx = cx.ccx();
2525     return PtrToInt(cx, v, ccx.int_type);
2526 }
2527
2528 fn p2i(ccx: @crate_ctxt, v: ValueRef) -> ValueRef {
2529     unsafe {
2530         return llvm::LLVMConstPtrToInt(v, ccx.int_type);
2531     }
2532 }
2533
2534 fn declare_intrinsics(llmod: ModuleRef) -> HashMap<~str, ValueRef> {
2535     let T_memcpy32_args: ~[TypeRef] =
2536         ~[T_ptr(T_i8()), T_ptr(T_i8()), T_i32(), T_i32(), T_i1()];
2537     let T_memcpy64_args: ~[TypeRef] =
2538         ~[T_ptr(T_i8()), T_ptr(T_i8()), T_i64(), T_i32(), T_i1()];
2539     let T_memset32_args: ~[TypeRef] =
2540         ~[T_ptr(T_i8()), T_i8(), T_i32(), T_i32(), T_i1()];
2541     let T_memset64_args: ~[TypeRef] =
2542         ~[T_ptr(T_i8()), T_i8(), T_i64(), T_i32(), T_i1()];
2543     let T_trap_args: ~[TypeRef] = ~[];
2544     let T_frameaddress_args: ~[TypeRef] = ~[T_i32()];
2545     let gcroot =
2546         decl_cdecl_fn(llmod, ~"llvm.gcroot",
2547                       T_fn(~[T_ptr(T_ptr(T_i8())), T_ptr(T_i8())],
2548                            T_void()));
2549     let gcread =
2550         decl_cdecl_fn(llmod, ~"llvm.gcread",
2551                       T_fn(~[T_ptr(T_i8()), T_ptr(T_ptr(T_i8()))],
2552                            T_void()));
2553     let memcpy32 =
2554         decl_cdecl_fn(llmod, ~"llvm.memcpy.p0i8.p0i8.i32",
2555                       T_fn(T_memcpy32_args, T_void()));
2556     let memcpy64 =
2557         decl_cdecl_fn(llmod, ~"llvm.memcpy.p0i8.p0i8.i64",
2558                       T_fn(T_memcpy64_args, T_void()));
2559     let memset32 =
2560         decl_cdecl_fn(llmod, ~"llvm.memset.p0i8.i32",
2561                       T_fn(T_memset32_args, T_void()));
2562     let memset64 =
2563         decl_cdecl_fn(llmod, ~"llvm.memset.p0i8.i64",
2564                       T_fn(T_memset64_args, T_void()));
2565     let trap = decl_cdecl_fn(llmod, ~"llvm.trap", T_fn(T_trap_args,
2566                                                       T_void()));
2567     let frameaddress = decl_cdecl_fn(llmod, ~"llvm.frameaddress",
2568                                      T_fn(T_frameaddress_args,
2569                                           T_ptr(T_i8())));
2570     let sqrtf32 = decl_cdecl_fn(llmod, ~"llvm.sqrt.f32",
2571                                 T_fn(~[T_f32()], T_f32()));
2572     let sqrtf64 = decl_cdecl_fn(llmod, ~"llvm.sqrt.f64",
2573                                 T_fn(~[T_f64()], T_f64()));
2574     let powif32 = decl_cdecl_fn(llmod, ~"llvm.powi.f32",
2575                                 T_fn(~[T_f32(), T_i32()], T_f32()));
2576     let powif64 = decl_cdecl_fn(llmod, ~"llvm.powi.f64",
2577                                 T_fn(~[T_f64(), T_i32()], T_f64()));
2578     let sinf32 = decl_cdecl_fn(llmod, ~"llvm.sin.f32",
2579                                 T_fn(~[T_f32()], T_f32()));
2580     let sinf64 = decl_cdecl_fn(llmod, ~"llvm.sin.f64",
2581                                 T_fn(~[T_f64()], T_f64()));
2582     let cosf32 = decl_cdecl_fn(llmod, ~"llvm.cos.f32",
2583                                 T_fn(~[T_f32()], T_f32()));
2584     let cosf64 = decl_cdecl_fn(llmod, ~"llvm.cos.f64",
2585                                 T_fn(~[T_f64()], T_f64()));
2586     let powf32 = decl_cdecl_fn(llmod, ~"llvm.pow.f32",
2587                                 T_fn(~[T_f32(), T_f32()], T_f32()));
2588     let powf64 = decl_cdecl_fn(llmod, ~"llvm.pow.f64",
2589                                 T_fn(~[T_f64(), T_f64()], T_f64()));
2590     let expf32 = decl_cdecl_fn(llmod, ~"llvm.exp.f32",
2591                                 T_fn(~[T_f32()], T_f32()));
2592     let expf64 = decl_cdecl_fn(llmod, ~"llvm.exp.f64",
2593                                 T_fn(~[T_f64()], T_f64()));
2594     let exp2f32 = decl_cdecl_fn(llmod, ~"llvm.exp2.f32",
2595                                 T_fn(~[T_f32()], T_f32()));
2596     let exp2f64 = decl_cdecl_fn(llmod, ~"llvm.exp2.f64",
2597                                 T_fn(~[T_f64()], T_f64()));
2598     let logf32 = decl_cdecl_fn(llmod, ~"llvm.log.f32",
2599                                 T_fn(~[T_f32()], T_f32()));
2600     let logf64 = decl_cdecl_fn(llmod, ~"llvm.log.f64",
2601                                 T_fn(~[T_f64()], T_f64()));
2602     let log10f32 = decl_cdecl_fn(llmod, ~"llvm.log10.f32",
2603                                 T_fn(~[T_f32()], T_f32()));
2604     let log10f64 = decl_cdecl_fn(llmod, ~"llvm.log10.f64",
2605                                 T_fn(~[T_f64()], T_f64()));
2606     let log2f32 = decl_cdecl_fn(llmod, ~"llvm.log2.f32",
2607                                 T_fn(~[T_f32()], T_f32()));
2608     let log2f64 = decl_cdecl_fn(llmod, ~"llvm.log2.f64",
2609                                 T_fn(~[T_f64()], T_f64()));
2610     let fmaf32 = decl_cdecl_fn(llmod, ~"llvm.fma.f32",
2611                                 T_fn(~[T_f32(), T_f32(), T_f32()], T_f32()));
2612     let fmaf64 = decl_cdecl_fn(llmod, ~"llvm.fma.f64",
2613                                 T_fn(~[T_f64(), T_f64(), T_f64()], T_f64()));
2614     let fabsf32 = decl_cdecl_fn(llmod, ~"llvm.fabs.f32",
2615                                 T_fn(~[T_f32()], T_f32()));
2616     let fabsf64 = decl_cdecl_fn(llmod, ~"llvm.fabs.f64",
2617                                 T_fn(~[T_f64()], T_f64()));
2618     let floorf32 = decl_cdecl_fn(llmod, ~"llvm.floor.f32",
2619                                 T_fn(~[T_f32()], T_f32()));
2620     let floorf64 = decl_cdecl_fn(llmod, ~"llvm.floor.f64",
2621                                 T_fn(~[T_f64()], T_f64()));
2622     let ceilf32 = decl_cdecl_fn(llmod, ~"llvm.ceil.f32",
2623                                 T_fn(~[T_f32()], T_f32()));
2624     let ceilf64 = decl_cdecl_fn(llmod, ~"llvm.ceil.f64",
2625                                 T_fn(~[T_f64()], T_f64()));
2626     let truncf32 = decl_cdecl_fn(llmod, ~"llvm.trunc.f32",
2627                                 T_fn(~[T_f32()], T_f32()));
2628     let truncf64 = decl_cdecl_fn(llmod, ~"llvm.trunc.f64",
2629                                 T_fn(~[T_f64()], T_f64()));
2630     let ctpop8 = decl_cdecl_fn(llmod, ~"llvm.ctpop.i8",
2631                                 T_fn(~[T_i8()], T_i8()));
2632     let ctpop16 = decl_cdecl_fn(llmod, ~"llvm.ctpop.i16",
2633                                 T_fn(~[T_i16()], T_i16()));
2634     let ctpop32 = decl_cdecl_fn(llmod, ~"llvm.ctpop.i32",
2635                                 T_fn(~[T_i32()], T_i32()));
2636     let ctpop64 = decl_cdecl_fn(llmod, ~"llvm.ctpop.i64",
2637                                 T_fn(~[T_i64()], T_i64()));
2638     let ctlz8 = decl_cdecl_fn(llmod, ~"llvm.ctlz.i8",
2639                                 T_fn(~[T_i8(), T_i1()], T_i8()));
2640     let ctlz16 = decl_cdecl_fn(llmod, ~"llvm.ctlz.i16",
2641                                 T_fn(~[T_i16(), T_i1()], T_i16()));
2642     let ctlz32 = decl_cdecl_fn(llmod, ~"llvm.ctlz.i32",
2643                                 T_fn(~[T_i32(), T_i1()], T_i32()));
2644     let ctlz64 = decl_cdecl_fn(llmod, ~"llvm.ctlz.i64",
2645                                 T_fn(~[T_i64(), T_i1()], T_i64()));
2646     let cttz8 = decl_cdecl_fn(llmod, ~"llvm.cttz.i8",
2647                                 T_fn(~[T_i8(), T_i1()], T_i8()));
2648     let cttz16 = decl_cdecl_fn(llmod, ~"llvm.cttz.i16",
2649                                 T_fn(~[T_i16(), T_i1()], T_i16()));
2650     let cttz32 = decl_cdecl_fn(llmod, ~"llvm.cttz.i32",
2651                                 T_fn(~[T_i32(), T_i1()], T_i32()));
2652     let cttz64 = decl_cdecl_fn(llmod, ~"llvm.cttz.i64",
2653                                 T_fn(~[T_i64(), T_i1()], T_i64()));
2654     let bswap16 = decl_cdecl_fn(llmod, ~"llvm.bswap.i16",
2655                                 T_fn(~[T_i16()], T_i16()));
2656     let bswap32 = decl_cdecl_fn(llmod, ~"llvm.bswap.i32",
2657                                 T_fn(~[T_i32()], T_i32()));
2658     let bswap64 = decl_cdecl_fn(llmod, ~"llvm.bswap.i64",
2659                                 T_fn(~[T_i64()], T_i64()));
2660
2661     let intrinsics = HashMap();
2662     intrinsics.insert(~"llvm.gcroot", gcroot);
2663     intrinsics.insert(~"llvm.gcread", gcread);
2664     intrinsics.insert(~"llvm.memcpy.p0i8.p0i8.i32", memcpy32);
2665     intrinsics.insert(~"llvm.memcpy.p0i8.p0i8.i64", memcpy64);
2666     intrinsics.insert(~"llvm.memset.p0i8.i32", memset32);
2667     intrinsics.insert(~"llvm.memset.p0i8.i64", memset64);
2668     intrinsics.insert(~"llvm.trap", trap);
2669     intrinsics.insert(~"llvm.frameaddress", frameaddress);
2670     intrinsics.insert(~"llvm.sqrt.f32", sqrtf32);
2671     intrinsics.insert(~"llvm.sqrt.f64", sqrtf64);
2672     intrinsics.insert(~"llvm.powi.f32", powif32);
2673     intrinsics.insert(~"llvm.powi.f64", powif64);
2674     intrinsics.insert(~"llvm.sin.f32", sinf32);
2675     intrinsics.insert(~"llvm.sin.f64", sinf64);
2676     intrinsics.insert(~"llvm.cos.f32", cosf32);
2677     intrinsics.insert(~"llvm.cos.f64", cosf64);
2678     intrinsics.insert(~"llvm.pow.f32", powf32);
2679     intrinsics.insert(~"llvm.pow.f64", powf64);
2680     intrinsics.insert(~"llvm.exp.f32", expf32);
2681     intrinsics.insert(~"llvm.exp.f64", expf64);
2682     intrinsics.insert(~"llvm.exp2.f32", exp2f32);
2683     intrinsics.insert(~"llvm.exp2.f64", exp2f64);
2684     intrinsics.insert(~"llvm.log.f32", logf32);
2685     intrinsics.insert(~"llvm.log.f64", logf64);
2686     intrinsics.insert(~"llvm.log10.f32", log10f32);
2687     intrinsics.insert(~"llvm.log10.f64", log10f64);
2688     intrinsics.insert(~"llvm.log2.f32", log2f32);
2689     intrinsics.insert(~"llvm.log2.f64", log2f64);
2690     intrinsics.insert(~"llvm.fma.f32", fmaf32);
2691     intrinsics.insert(~"llvm.fma.f64", fmaf64);
2692     intrinsics.insert(~"llvm.fabs.f32", fabsf32);
2693     intrinsics.insert(~"llvm.fabs.f64", fabsf64);
2694     intrinsics.insert(~"llvm.floor.f32", floorf32);
2695     intrinsics.insert(~"llvm.floor.f64", floorf64);
2696     intrinsics.insert(~"llvm.ceil.f32", ceilf32);
2697     intrinsics.insert(~"llvm.ceil.f64", ceilf64);
2698     intrinsics.insert(~"llvm.trunc.f32", truncf32);
2699     intrinsics.insert(~"llvm.trunc.f64", truncf64);
2700     intrinsics.insert(~"llvm.ctpop.i8", ctpop8);
2701     intrinsics.insert(~"llvm.ctpop.i16", ctpop16);
2702     intrinsics.insert(~"llvm.ctpop.i32", ctpop32);
2703     intrinsics.insert(~"llvm.ctpop.i64", ctpop64);
2704     intrinsics.insert(~"llvm.ctlz.i8", ctlz8);
2705     intrinsics.insert(~"llvm.ctlz.i16", ctlz16);
2706     intrinsics.insert(~"llvm.ctlz.i32", ctlz32);
2707     intrinsics.insert(~"llvm.ctlz.i64", ctlz64);
2708     intrinsics.insert(~"llvm.cttz.i8", cttz8);
2709     intrinsics.insert(~"llvm.cttz.i16", cttz16);
2710     intrinsics.insert(~"llvm.cttz.i32", cttz32);
2711     intrinsics.insert(~"llvm.cttz.i64", cttz64);
2712     intrinsics.insert(~"llvm.bswap.i16", bswap16);
2713     intrinsics.insert(~"llvm.bswap.i32", bswap32);
2714     intrinsics.insert(~"llvm.bswap.i64", bswap64);
2715
2716     return intrinsics;
2717 }
2718
2719 fn declare_dbg_intrinsics(llmod: ModuleRef,
2720                           intrinsics: HashMap<~str, ValueRef>) {
2721     let declare =
2722         decl_cdecl_fn(llmod, ~"llvm.dbg.declare",
2723                       T_fn(~[T_metadata(), T_metadata()], T_void()));
2724     let value =
2725         decl_cdecl_fn(llmod, ~"llvm.dbg.value",
2726                       T_fn(~[T_metadata(), T_i64(), T_metadata()],
2727                            T_void()));
2728     intrinsics.insert(~"llvm.dbg.declare", declare);
2729     intrinsics.insert(~"llvm.dbg.value", value);
2730 }
2731
2732 fn trap(bcx: block) {
2733     let v: ~[ValueRef] = ~[];
2734     match bcx.ccx().intrinsics.find(~"llvm.trap") {
2735       Some(x) => { Call(bcx, x, v); },
2736       _ => bcx.sess().bug(~"unbound llvm.trap in trap")
2737     }
2738 }
2739
2740 fn decl_gc_metadata(ccx: @crate_ctxt, llmod_id: ~str) {
2741     if !ccx.sess.opts.gc || !ccx.uses_gc {
2742         return;
2743     }
2744
2745     let gc_metadata_name = ~"_gc_module_metadata_" + llmod_id;
2746     let gc_metadata = do str::as_c_str(gc_metadata_name) |buf| {
2747         unsafe {
2748             llvm::LLVMAddGlobal(ccx.llmod, T_i32(), buf)
2749         }
2750     };
2751     unsafe {
2752         llvm::LLVMSetGlobalConstant(gc_metadata, True);
2753         lib::llvm::SetLinkage(gc_metadata, lib::llvm::ExternalLinkage);
2754         ccx.module_data.insert(~"_gc_module_metadata", gc_metadata);
2755     }
2756 }
2757
2758 fn create_module_map(ccx: @crate_ctxt) -> ValueRef {
2759     let elttype = T_struct(~[ccx.int_type, ccx.int_type]);
2760     let maptype = T_array(elttype, ccx.module_data.size() + 1u);
2761     let map = str::as_c_str(~"_rust_mod_map", |buf| {
2762         unsafe {
2763             llvm::LLVMAddGlobal(ccx.llmod, maptype, buf)
2764         }
2765     });
2766     unsafe {
2767         lib::llvm::SetLinkage(map, lib::llvm::InternalLinkage);
2768     }
2769     let mut elts: ~[ValueRef] = ~[];
2770     for ccx.module_data.each |key, val| {
2771         let elt = C_struct(~[p2i(ccx, C_cstr(ccx, key)),
2772                             p2i(ccx, val)]);
2773         elts.push(elt);
2774     }
2775     let term = C_struct(~[C_int(ccx, 0), C_int(ccx, 0)]);
2776     elts.push(term);
2777     unsafe {
2778         llvm::LLVMSetInitializer(map, C_array(elttype, elts));
2779     }
2780     return map;
2781 }
2782
2783
2784 fn decl_crate_map(sess: session::Session, mapmeta: link_meta,
2785                   llmod: ModuleRef) -> ValueRef {
2786     let targ_cfg = sess.targ_cfg;
2787     let int_type = T_int(targ_cfg);
2788     let mut n_subcrates = 1;
2789     let cstore = sess.cstore;
2790     while cstore::have_crate_data(cstore, n_subcrates) { n_subcrates += 1; }
2791     let mapname = if sess.building_library {
2792         mapmeta.name + ~"_" + mapmeta.vers + ~"_" + mapmeta.extras_hash
2793     } else { ~"toplevel" };
2794     let sym_name = ~"_rust_crate_map_" + mapname;
2795     let arrtype = T_array(int_type, n_subcrates as uint);
2796     let maptype = T_struct(~[T_i32(), T_ptr(T_i8()), int_type, arrtype]);
2797     let map = str::as_c_str(sym_name, |buf| {
2798         unsafe {
2799             llvm::LLVMAddGlobal(llmod, maptype, buf)
2800         }
2801     });
2802     lib::llvm::SetLinkage(map, lib::llvm::ExternalLinkage);
2803     return map;
2804 }
2805
2806 fn fill_crate_map(ccx: @crate_ctxt, map: ValueRef) {
2807     let mut subcrates: ~[ValueRef] = ~[];
2808     let mut i = 1;
2809     let cstore = ccx.sess.cstore;
2810     while cstore::have_crate_data(cstore, i) {
2811         let cdata = cstore::get_crate_data(cstore, i);
2812         let nm = ~"_rust_crate_map_" + cdata.name +
2813             ~"_" + cstore::get_crate_vers(cstore, i) +
2814             ~"_" + cstore::get_crate_hash(cstore, i);
2815         let cr = str::as_c_str(nm, |buf| {
2816             unsafe {
2817                 llvm::LLVMAddGlobal(ccx.llmod, ccx.int_type, buf)
2818             }
2819         });
2820         subcrates.push(p2i(ccx, cr));
2821         i += 1;
2822     }
2823     subcrates.push(C_int(ccx, 0));
2824
2825     let llannihilatefn;
2826     let annihilate_def_id = ccx.tcx.lang_items.annihilate_fn();
2827     if annihilate_def_id.crate == ast::local_crate {
2828         llannihilatefn = get_item_val(ccx, annihilate_def_id.node);
2829     } else {
2830         let annihilate_fn_type = csearch::get_type(ccx.tcx,
2831                                                    annihilate_def_id).ty;
2832         llannihilatefn = trans_external_path(ccx,
2833                                              annihilate_def_id,
2834                                              annihilate_fn_type);
2835     }
2836
2837     unsafe {
2838         llvm::LLVMSetInitializer(map, C_struct(
2839             ~[C_i32(1),
2840               lib::llvm::llvm::LLVMConstPointerCast(llannihilatefn,
2841                                                     T_ptr(T_i8())),
2842               p2i(ccx, create_module_map(ccx)),
2843               C_array(ccx.int_type, subcrates)]));
2844     }
2845 }
2846
2847 fn crate_ctxt_to_encode_parms(cx: @crate_ctxt) -> encoder::encode_parms {
2848     // XXX: Bad copy of `c`, whatever it is.
2849     let encode_inlined_item =
2850         |a,b,c,d| astencode::encode_inlined_item(a, b, copy c, d, cx.maps);
2851
2852     return {
2853         diag: cx.sess.diagnostic(),
2854         tcx: cx.tcx,
2855         reachable: cx.reachable,
2856         reexports2: cx.exp_map2,
2857         item_symbols: cx.item_symbols,
2858         discrim_symbols: cx.discrim_symbols,
2859         link_meta: /*bad*/copy cx.link_meta,
2860         cstore: cx.sess.cstore,
2861         encode_inlined_item: encode_inlined_item
2862     };
2863 }
2864
2865 fn write_metadata(cx: @crate_ctxt, crate: @ast::crate) {
2866     if !cx.sess.building_library { return; }
2867     let encode_parms = crate_ctxt_to_encode_parms(cx);
2868     let llmeta = C_bytes(encoder::encode_metadata(encode_parms, crate));
2869     let llconst = C_struct(~[llmeta]);
2870     let mut llglobal = str::as_c_str(~"rust_metadata", |buf| {
2871         unsafe {
2872             llvm::LLVMAddGlobal(cx.llmod, val_ty(llconst), buf)
2873         }
2874     });
2875     unsafe {
2876         llvm::LLVMSetInitializer(llglobal, llconst);
2877         str::as_c_str(cx.sess.targ_cfg.target_strs.meta_sect_name, |buf| {
2878             llvm::LLVMSetSection(llglobal, buf)
2879         });
2880         lib::llvm::SetLinkage(llglobal, lib::llvm::InternalLinkage);
2881
2882         let t_ptr_i8 = T_ptr(T_i8());
2883         llglobal = llvm::LLVMConstBitCast(llglobal, t_ptr_i8);
2884         let llvm_used = str::as_c_str(~"llvm.used", |buf| {
2885             llvm::LLVMAddGlobal(cx.llmod, T_array(t_ptr_i8, 1u), buf)
2886         });
2887         lib::llvm::SetLinkage(llvm_used, lib::llvm::AppendingLinkage);
2888         llvm::LLVMSetInitializer(llvm_used, C_array(t_ptr_i8, ~[llglobal]));
2889     }
2890 }
2891
2892 // Writes the current ABI version into the crate.
2893 fn write_abi_version(ccx: @crate_ctxt) {
2894     mk_global(ccx, ~"rust_abi_version", C_uint(ccx, abi::abi_version),
2895                      false);
2896 }
2897
2898 fn trans_crate(sess: session::Session,
2899                crate: @ast::crate,
2900                tcx: ty::ctxt,
2901                output: &Path,
2902                emap2: resolve::ExportMap2,
2903                maps: astencode::maps)
2904             -> (ModuleRef, link_meta) {
2905
2906     let symbol_hasher = @hash::default_state();
2907     let link_meta =
2908         link::build_link_meta(sess, *crate, output, symbol_hasher);
2909     let reachable = reachable::find_reachable(crate.node.module, emap2, tcx,
2910                                               maps.method_map);
2911
2912     // Append ".rc" to crate name as LLVM module identifier.
2913     //
2914     // LLVM code generator emits a ".file filename" directive
2915     // for ELF backends. Value of the "filename" is set as the
2916     // LLVM module identifier.  Due to a LLVM MC bug[1], LLVM
2917     // crashes if the module identifer is same as other symbols
2918     // such as a function name in the module.
2919     // 1. http://llvm.org/bugs/show_bug.cgi?id=11479
2920     let llmod_id = link_meta.name + ~".rc";
2921
2922     unsafe {
2923         let llmod = str::as_c_str(llmod_id, |buf| {
2924             llvm::LLVMModuleCreateWithNameInContext
2925                 (buf, llvm::LLVMGetGlobalContext())
2926         });
2927         let data_layout = /*bad*/copy sess.targ_cfg.target_strs.data_layout;
2928         let targ_triple = /*bad*/copy sess.targ_cfg.target_strs.target_triple;
2929         let _: () =
2930             str::as_c_str(data_layout,
2931                         |buf| llvm::LLVMSetDataLayout(llmod, buf));
2932         let _: () =
2933             str::as_c_str(targ_triple,
2934                         |buf| llvm::LLVMSetTarget(llmod, buf));
2935         let targ_cfg = sess.targ_cfg;
2936         let td = mk_target_data(
2937             /*bad*/copy sess.targ_cfg.target_strs.data_layout);
2938         let tn = mk_type_names();
2939         let intrinsics = declare_intrinsics(llmod);
2940         if sess.opts.extra_debuginfo {
2941             declare_dbg_intrinsics(llmod, intrinsics);
2942         }
2943         let int_type = T_int(targ_cfg);
2944         let float_type = T_float(targ_cfg);
2945         let task_type = T_task(targ_cfg);
2946         let taskptr_type = T_ptr(task_type);
2947         lib::llvm::associate_type(tn, ~"taskptr", taskptr_type);
2948         let tydesc_type = T_tydesc(targ_cfg);
2949         lib::llvm::associate_type(tn, ~"tydesc", tydesc_type);
2950         let crate_map = decl_crate_map(sess, link_meta, llmod);
2951         let dbg_cx = if sess.opts.debuginfo {
2952             Some(debuginfo::mk_ctxt(copy llmod_id, sess.parse_sess.interner))
2953         } else {
2954             None
2955         };
2956
2957         let ccx = @crate_ctxt {
2958               sess: sess,
2959               llmod: llmod,
2960               td: td,
2961               tn: tn,
2962               externs: HashMap(),
2963               intrinsics: intrinsics,
2964               item_vals: HashMap(),
2965               exp_map2: emap2,
2966               reachable: reachable,
2967               item_symbols: HashMap(),
2968               mut main_fn: None::<ValueRef>,
2969               link_meta: copy link_meta,    // XXX: Bad copy.
2970               enum_sizes: ty::new_ty_hash(),
2971               discrims: HashMap(),
2972               discrim_symbols: HashMap(),
2973               tydescs: ty::new_ty_hash(),
2974               mut finished_tydescs: false,
2975               external: HashMap(),
2976               monomorphized: HashMap(),
2977               monomorphizing: HashMap(),
2978               type_use_cache: HashMap(),
2979               vtables: map::HashMap(),
2980               const_cstr_cache: HashMap(),
2981               const_globals: HashMap(),
2982               const_values: HashMap(),
2983               module_data: HashMap(),
2984               lltypes: ty::new_ty_hash(),
2985               names: new_namegen(sess.parse_sess.interner),
2986               next_addrspace: new_addrspace_gen(),
2987               symbol_hasher: symbol_hasher,
2988               type_hashcodes: ty::new_ty_hash(),
2989               type_short_names: ty::new_ty_hash(),
2990               all_llvm_symbols: HashMap(),
2991               tcx: tcx,
2992               maps: maps,
2993               stats:
2994                   {mut n_static_tydescs: 0u,
2995                    mut n_glues_created: 0u,
2996                    mut n_null_glues: 0u,
2997                    mut n_real_glues: 0u,
2998                    mut n_fns: 0u,
2999                    mut n_monos: 0u,
3000                    mut n_inlines: 0u,
3001                    mut n_closures: 0u,
3002                    llvm_insn_ctxt: @mut ~[],
3003                    llvm_insns: HashMap(),
3004                    fn_times: @mut ~[]},
3005               upcalls: upcall::declare_upcalls(targ_cfg, llmod),
3006               tydesc_type: tydesc_type,
3007               int_type: int_type,
3008               float_type: float_type,
3009               task_type: task_type,
3010               opaque_vec_type: T_opaque_vec(targ_cfg),
3011               builder: BuilderRef_res(unsafe { llvm::LLVMCreateBuilder() }),
3012               shape_cx: mk_ctxt(llmod),
3013               crate_map: crate_map,
3014               mut uses_gc: false,
3015               dbg_cx: dbg_cx,
3016               mut do_not_commit_warning_issued: false
3017         };
3018
3019         {
3020             let _icx = ccx.insn_ctxt("data");
3021             trans_constants(ccx, crate);
3022         }
3023
3024         {
3025             let _icx = ccx.insn_ctxt("text");
3026             trans_mod(ccx, crate.node.module);
3027         }
3028
3029         decl_gc_metadata(ccx, llmod_id);
3030         fill_crate_map(ccx, crate_map);
3031         glue::emit_tydescs(ccx);
3032         write_abi_version(ccx);
3033
3034         // Translate the metadata.
3035         write_metadata(ccx, crate);
3036         if ccx.sess.trans_stats() {
3037             io::println(~"--- trans stats ---");
3038             io::println(fmt!("n_static_tydescs: %u",
3039                              ccx.stats.n_static_tydescs));
3040             io::println(fmt!("n_glues_created: %u",
3041                              ccx.stats.n_glues_created));
3042             io::println(fmt!("n_null_glues: %u", ccx.stats.n_null_glues));
3043             io::println(fmt!("n_real_glues: %u", ccx.stats.n_real_glues));
3044
3045             io::println(fmt!("n_fns: %u", ccx.stats.n_fns));
3046             io::println(fmt!("n_monos: %u", ccx.stats.n_monos));
3047             io::println(fmt!("n_inlines: %u", ccx.stats.n_inlines));
3048             io::println(fmt!("n_closures: %u", ccx.stats.n_closures));
3049         }
3050
3051         if ccx.sess.count_llvm_insns() {
3052             for ccx.stats.llvm_insns.each |k, v| {
3053                 io::println(fmt!("%-7u %s", v, k));
3054             }
3055         }
3056         return (llmod, link_meta);
3057     }
3058 }
3059 //
3060 // Local Variables:
3061 // mode: rust
3062 // fill-column: 78;
3063 // indent-tabs-mode: nil
3064 // c-basic-offset: 4
3065 // buffer-file-coding-system: utf-8-unix
3066 // End:
3067 //