]> git.lizzy.rs Git - rust.git/blob - src/comp/middle/trans_common.rs
Statically allocate static dicts
[rust.git] / src / comp / middle / trans_common.rs
1 /**
2    Code that is useful in various trans modules.
3
4 */
5
6 import core::{int, vec, str, uint, option, unsafe};
7 import vec::to_ptr;
8 import std::map::hashmap;
9 import option::some;
10 import syntax::ast;
11 import driver::session;
12 import middle::{resolve, ty};
13 import back::{link, abi, upcall};
14 import util::common::*;
15 import syntax::codemap::span;
16 import lib::llvm::{llvm, target_data, type_names};
17 import lib::llvm::llvm::{ModuleRef, ValueRef, TypeRef, BasicBlockRef};
18 import lib::llvm::{True, False, Bool};
19 import metadata::{csearch};
20
21 // FIXME: These should probably be pulled in here too.
22 import trans::{type_of_fn, drop_ty};
23
24 obj namegen(mutable i: int) {
25     fn next(prefix: str) -> str { i += 1; ret prefix + int::str(i); }
26 }
27
28 type derived_tydesc_info = {lltydesc: ValueRef, escapes: bool};
29
30 tag tydesc_kind {
31     tk_static; // Static (monomorphic) type descriptor.
32     tk_param; // Type parameter.
33     tk_derived; // Derived from a typaram or another derived tydesc.
34 }
35
36 type tydesc_info =
37     {ty: ty::t,
38      tydesc: ValueRef,
39      size: ValueRef,
40      align: ValueRef,
41      mutable take_glue: option::t<ValueRef>,
42      mutable drop_glue: option::t<ValueRef>,
43      mutable free_glue: option::t<ValueRef>,
44      mutable cmp_glue: option::t<ValueRef>,
45      ty_params: [uint],
46      is_obj_body: bool};
47
48 /*
49  * A note on nomenclature of linking: "upcall", "extern" and "native".
50  *
51  * An "extern" is an LLVM symbol we wind up emitting an undefined external
52  * reference to. This means "we don't have the thing in this compilation unit,
53  * please make sure you link it in at runtime". This could be a reference to
54  * C code found in a C library, or rust code found in a rust crate.
55  *
56  * A "native" is an extern that references C code. Called with cdecl.
57  *
58  * An upcall is a native call generated by the compiler (not corresponding to
59  * any user-written call in the code) into librustrt, to perform some helper
60  * task such as bringing a task to life, allocating memory, etc.
61  *
62  */
63 type stats =
64     {mutable n_static_tydescs: uint,
65      mutable n_derived_tydescs: uint,
66      mutable n_glues_created: uint,
67      mutable n_null_glues: uint,
68      mutable n_real_glues: uint,
69      fn_times: @mutable [{ident: str, time: int}]};
70
71 resource BuilderRef_res(B: llvm::BuilderRef) { llvm::LLVMDisposeBuilder(B); }
72
73 // Crate context.  Every crate we compile has one of these.
74 type crate_ctxt =
75     // A mapping from the def_id of each item in this crate to the address
76     // of the first instruction of the item's definition in the executable
77     // we're generating.
78     // TODO: hashmap<tup(tag_id,subtys), @tag_info>
79     {sess: session::session,
80      llmod: ModuleRef,
81      td: target_data,
82      tn: type_names,
83      externs: hashmap<str, ValueRef>,
84      intrinsics: hashmap<str, ValueRef>,
85      item_ids: hashmap<ast::node_id, ValueRef>,
86      ast_map: ast_map::map,
87      exp_map: resolve::exp_map,
88      item_symbols: hashmap<ast::node_id, str>,
89      mutable main_fn: option::t<ValueRef>,
90      link_meta: link::link_meta,
91      tag_sizes: hashmap<ty::t, uint>,
92      discrims: hashmap<ast::def_id, ValueRef>,
93      discrim_symbols: hashmap<ast::node_id, str>,
94      consts: hashmap<ast::node_id, ValueRef>,
95      tydescs: hashmap<ty::t, @tydesc_info>,
96      dicts: hashmap<dict_id, ValueRef>,
97      module_data: hashmap<str, ValueRef>,
98      lltypes: hashmap<ty::t, TypeRef>,
99      names: namegen,
100      sha: std::sha1::sha1,
101      type_sha1s: hashmap<ty::t, str>,
102      type_short_names: hashmap<ty::t, str>,
103      tcx: ty::ctxt,
104      mut_map: mut::mut_map,
105      copy_map: alias::copy_map,
106      last_uses: last_use::last_uses,
107      method_map: typeck::method_map,
108      dict_map: typeck::dict_map,
109      stats: stats,
110      upcalls: @upcall::upcalls,
111      rust_object_type: TypeRef,
112      tydesc_type: TypeRef,
113      int_type: TypeRef,
114      float_type: TypeRef,
115      task_type: TypeRef,
116      opaque_vec_type: TypeRef,
117      builder: BuilderRef_res,
118      shape_cx: shape::ctxt,
119      gc_cx: gc::ctxt,
120      crate_map: ValueRef,
121      dbg_cx: option::t<@debuginfo::debug_ctxt>};
122
123 type local_ctxt =
124     {path: [str],
125      module_path: [str],
126      obj_typarams: [ast::ty_param],
127      obj_fields: [ast::obj_field],
128      ccx: @crate_ctxt};
129
130 // Types used for llself.
131 type val_self_pair = {v: ValueRef, t: ty::t};
132
133 tag local_val { local_mem(ValueRef); local_imm(ValueRef); }
134
135 type fn_ty_param = {desc: ValueRef, dicts: option::t<[ValueRef]>};
136
137 // Function context.  Every LLVM function we create will have one of
138 // these.
139 type fn_ctxt =
140     // The ValueRef returned from a call to llvm::LLVMAddFunction; the
141     // address of the first instruction in the sequence of
142     // instructions for this function that will go in the .text
143     // section of the executable we're generating.
144
145     // The three implicit arguments that arrive in the function we're
146     // creating.  For instance, foo(int, int) is really foo(ret*,
147     // task*, env*, int, int).  These are also available via
148     // llvm::LLVMGetParam(llfn, uint) where uint = 1, 2, 0
149     // respectively, but we unpack them into these fields for
150     // convenience.
151
152     // Points to the current task.
153
154     // Points to the current environment (bindings of variables to
155     // values), if this is a regular function; points to the current
156     // object, if this is a method.
157
158     // Points to where the return value of this function should end
159     // up.
160
161     // The next three elements: "hoisted basic blocks" containing
162     // administrative activities that have to happen in only one place in
163     // the function, due to LLVM's quirks.
164
165     // A block for all the function's static allocas, so that LLVM
166     // will coalesce them into a single alloca call.
167
168     // A block containing code that copies incoming arguments to space
169     // already allocated by code in one of the llallocas blocks.
170     // (LLVM requires that arguments be copied to local allocas before
171     // allowing most any operation to be performed on them.)
172
173     // The first block containing derived tydescs received from the
174     // runtime.  See description of derived_tydescs, below.
175
176     // The last block of the llderivedtydescs group.
177
178     // A block for all of the dynamically sized allocas.  This must be
179     // after llderivedtydescs, because these sometimes depend on
180     // information computed from derived tydescs.
181
182     // The token used to clear the dynamic allocas at the end of this frame.
183
184     // The 'self' object currently in use in this function, if there
185     // is one.
186
187     // If this function is actually a iter, a block containing the
188     // code called whenever the iter calls 'put'.
189
190     // The next four items: hash tables mapping from AST def_ids to
191     // LLVM-stuff-in-the-frame.
192
193     // Maps arguments to allocas created for them in llallocas.
194
195     // Maps fields in objects to pointers into the interior of
196     // llself's body.
197
198     // Maps the def_ids for local variables to the allocas created for
199     // them in llallocas.
200
201     // The same as above, but for variables accessed via the frame
202     // pointer we pass into an iter, for access to the static
203     // environment of the iter-calling frame.
204
205     // For convenience, a vector of the incoming tydescs for each of
206     // this functions type parameters, fetched via llvm::LLVMGetParam.
207     // For example, for a function foo::<A, B, C>(), lltydescs contains
208     // the ValueRefs for the tydescs for A, B, and C.
209
210     // Derived tydescs are tydescs created at runtime, for types that
211     // involve type parameters inside type constructors.  For example,
212     // suppose a function parameterized by T creates a vector of type
213     // [T].  The function doesn't know what T is until runtime, and
214     // the function's caller knows T but doesn't know that a vector is
215     // involved.  So a tydesc for [T] can't be created until runtime,
216     // when information about both "[T]" and "T" are available.  When
217     // such a tydesc is created, we cache it in the derived_tydescs
218     // table for the next time that such a tydesc is needed.
219
220     // The node_id of the function, or -1 if it doesn't correspond to
221     // a user-defined function.
222
223     // The source span where this function comes from, for error
224     // reporting.
225
226     // This function's enclosing local context.
227     {llfn: ValueRef,
228      llenv: ValueRef,
229      llretptr: ValueRef,
230      mutable llstaticallocas: BasicBlockRef,
231      mutable llloadenv: BasicBlockRef,
232      mutable llderivedtydescs_first: BasicBlockRef,
233      mutable llderivedtydescs: BasicBlockRef,
234      mutable lldynamicallocas: BasicBlockRef,
235      mutable llreturn: BasicBlockRef,
236      mutable llobstacktoken: option::t<ValueRef>,
237      mutable llself: option::t<val_self_pair>,
238      llargs: hashmap<ast::node_id, local_val>,
239      llobjfields: hashmap<ast::node_id, ValueRef>,
240      lllocals: hashmap<ast::node_id, local_val>,
241      llupvars: hashmap<ast::node_id, ValueRef>,
242      mutable lltyparams: [fn_ty_param],
243      derived_tydescs: hashmap<ty::t, derived_tydesc_info>,
244      id: ast::node_id,
245      ret_style: ast::ret_style,
246      sp: span,
247      lcx: @local_ctxt};
248
249 tag cleanup {
250     clean(fn@(@block_ctxt) -> @block_ctxt);
251     clean_temp(ValueRef, fn@(@block_ctxt) -> @block_ctxt);
252 }
253
254 fn add_clean(cx: @block_ctxt, val: ValueRef, ty: ty::t) {
255     if !ty::type_needs_drop(bcx_tcx(cx), ty) { ret; }
256     let scope_cx = find_scope_cx(cx);
257     scope_cx.cleanups += [clean(bind drop_ty(_, val, ty))];
258     scope_cx.lpad_dirty = true;
259 }
260 fn add_clean_temp(cx: @block_ctxt, val: ValueRef, ty: ty::t) {
261     if !ty::type_needs_drop(bcx_tcx(cx), ty) { ret; }
262     fn do_drop(bcx: @block_ctxt, val: ValueRef, ty: ty::t) ->
263        @block_ctxt {
264         if ty::type_is_immediate(bcx_tcx(bcx), ty) {
265             ret trans::drop_ty_immediate(bcx, val, ty);
266         } else {
267             ret drop_ty(bcx, val, ty);
268         }
269     }
270     let scope_cx = find_scope_cx(cx);
271     scope_cx.cleanups +=
272         [clean_temp(val, bind do_drop(_, val, ty))];
273     scope_cx.lpad_dirty = true;
274 }
275 fn add_clean_temp_mem(cx: @block_ctxt, val: ValueRef, ty: ty::t) {
276     if !ty::type_needs_drop(bcx_tcx(cx), ty) { ret; }
277     let scope_cx = find_scope_cx(cx);
278     scope_cx.cleanups += [clean_temp(val, bind drop_ty(_, val, ty))];
279     scope_cx.lpad_dirty = true;
280 }
281 fn add_clean_free(cx: @block_ctxt, ptr: ValueRef, shared: bool) {
282     let scope_cx = find_scope_cx(cx);
283     let free_fn = if shared { bind trans::trans_shared_free(_, ptr) }
284                   else { bind trans::trans_free_if_not_gc(_, ptr) };
285     scope_cx.cleanups += [clean_temp(ptr, free_fn)];
286     scope_cx.lpad_dirty = true;
287 }
288
289 // Note that this only works for temporaries. We should, at some point, move
290 // to a system where we can also cancel the cleanup on local variables, but
291 // this will be more involved. For now, we simply zero out the local, and the
292 // drop glue checks whether it is zero.
293 fn revoke_clean(cx: @block_ctxt, val: ValueRef) {
294     let sc_cx = find_scope_cx(cx);
295     let found = -1;
296     let i = 0;
297     for c: cleanup in sc_cx.cleanups {
298         alt c {
299           clean_temp(v, _) {
300             if v as uint == val as uint { found = i; break; }
301           }
302           _ { }
303         }
304         i += 1;
305     }
306     // The value does not have a cleanup associated with it.
307     if found == -1 { ret; }
308     // We found the cleanup and remove it
309     sc_cx.cleanups =
310         vec::slice(sc_cx.cleanups, 0u, found as uint) +
311             vec::slice(sc_cx.cleanups, (found as uint) + 1u,
312                             vec::len(sc_cx.cleanups));
313     sc_cx.lpad_dirty = true;
314     ret;
315 }
316
317 fn get_res_dtor(ccx: @crate_ctxt, sp: span, did: ast::def_id, inner_t: ty::t)
318    -> ValueRef {
319     if did.crate == ast::local_crate {
320         alt ccx.item_ids.find(did.node) {
321           some(x) { ret x; }
322           _ { ccx.tcx.sess.bug("get_res_dtor: can't find resource dtor!"); }
323         }
324     }
325
326     let param_bounds = ty::lookup_item_type(ccx.tcx, did).bounds;
327     let nil_res = ty::mk_nil(ccx.tcx);
328     // FIXME: Silly check -- mk_nil should have a postcondition
329     check non_ty_var(ccx, nil_res);
330     let f_t = type_of_fn(ccx, sp, false,
331                          [{mode: ast::by_ref, ty: inner_t}],
332                          nil_res, *param_bounds);
333     ret trans::get_extern_const(ccx.externs, ccx.llmod,
334                                 csearch::get_symbol(ccx.sess.get_cstore(),
335                                                     did), f_t);
336 }
337
338 tag block_kind {
339
340
341     // A scope block is a basic block created by translating a block { ... }
342     // the the source language.  Since these blocks create variable scope, any
343     // variables created in them that are still live at the end of the block
344     // must be dropped and cleaned up when the block ends.
345     SCOPE_BLOCK;
346
347
348     // A basic block created from the body of a loop.  Contains pointers to
349     // which block to jump to in the case of "continue" or "break", with the
350     // "continue" block optional, because "while" and "do while" don't support
351     // "continue" (TODO: is this intentional?)
352     LOOP_SCOPE_BLOCK(option::t<@block_ctxt>, @block_ctxt);
353
354
355     // A non-scope block is a basic block created as a translation artifact
356     // from translating code that expresses conditional logic rather than by
357     // explicit { ... } block structure in the source language.  It's called a
358     // non-scope block because it doesn't introduce a new variable scope.
359     NON_SCOPE_BLOCK;
360 }
361
362
363 // Basic block context.  We create a block context for each basic block
364 // (single-entry, single-exit sequence of instructions) we generate from Rust
365 // code.  Each basic block we generate is attached to a function, typically
366 // with many basic blocks per function.  All the basic blocks attached to a
367 // function are organized as a directed graph.
368 type block_ctxt =
369     // The BasicBlockRef returned from a call to
370     // llvm::LLVMAppendBasicBlock(llfn, name), which adds a basic
371     // block to the function pointed to by llfn.  We insert
372     // instructions into that block by way of this block context.
373     // The block pointing to this one in the function's digraph.
374     // The 'kind' of basic block this is.
375     // A list of functions that run at the end of translating this
376     // block, cleaning up any variables that were introduced in the
377     // block and need to go out of scope at the end of it.
378     // The source span where this block comes from, for error
379     // reporting. FIXME this is not currently reliable
380     // The function context for the function to which this block is
381     // attached.
382     {llbb: BasicBlockRef,
383      mutable terminated: bool,
384      mutable unreachable: bool,
385      parent: block_parent,
386      kind: block_kind,
387      mutable cleanups: [cleanup],
388      mutable lpad_dirty: bool,
389      mutable lpad: option::t<BasicBlockRef>,
390      sp: span,
391      fcx: @fn_ctxt};
392
393 // FIXME: we should be able to use option::t<@block_parent> here but
394 // the infinite-tag check in rustboot gets upset.
395 tag block_parent { parent_none; parent_some(@block_ctxt); }
396
397 type result = {bcx: @block_ctxt, val: ValueRef};
398 type result_t = {bcx: @block_ctxt, val: ValueRef, ty: ty::t};
399
400 fn extend_path(cx: @local_ctxt, name: str) -> @local_ctxt {
401     ret @{path: cx.path + [name] with *cx};
402 }
403
404 fn rslt(bcx: @block_ctxt, val: ValueRef) -> result {
405     {bcx: bcx, val: val}
406 }
407
408 fn ty_str(tn: type_names, t: TypeRef) -> str {
409     ret lib::llvm::type_to_str(tn, t);
410 }
411
412 fn val_ty(&&v: ValueRef) -> TypeRef { ret llvm::LLVMTypeOf(v); }
413
414 fn val_str(tn: type_names, v: ValueRef) -> str { ret ty_str(tn, val_ty(v)); }
415
416 // Returns the nth element of the given LLVM structure type.
417 fn struct_elt(llstructty: TypeRef, n: uint) -> TypeRef unsafe {
418     let elt_count = llvm::LLVMCountStructElementTypes(llstructty);
419     assert (n < elt_count);
420     let elt_tys = vec::init_elt(T_nil(), elt_count);
421     llvm::LLVMGetStructElementTypes(llstructty, to_ptr(elt_tys));
422     ret llvm::LLVMGetElementType(elt_tys[n]);
423 }
424
425 fn find_scope_cx(cx: @block_ctxt) -> @block_ctxt {
426     if cx.kind != NON_SCOPE_BLOCK { ret cx; }
427     alt cx.parent {
428       parent_some(b) { ret find_scope_cx(b); }
429       parent_none. {
430         cx.fcx.lcx.ccx.sess.bug("trans::find_scope_cx() " +
431                                     "called on parentless block_ctxt");
432       }
433     }
434 }
435
436 // Accessors
437 // TODO: When we have overloading, simplify these names!
438
439 pure fn bcx_tcx(bcx: @block_ctxt) -> ty::ctxt { ret bcx.fcx.lcx.ccx.tcx; }
440 pure fn bcx_ccx(bcx: @block_ctxt) -> @crate_ctxt { ret bcx.fcx.lcx.ccx; }
441 pure fn bcx_lcx(bcx: @block_ctxt) -> @local_ctxt { ret bcx.fcx.lcx; }
442 pure fn bcx_fcx(bcx: @block_ctxt) -> @fn_ctxt { ret bcx.fcx; }
443 pure fn fcx_ccx(fcx: @fn_ctxt) -> @crate_ctxt { ret fcx.lcx.ccx; }
444 pure fn fcx_tcx(fcx: @fn_ctxt) -> ty::ctxt { ret fcx.lcx.ccx.tcx; }
445 pure fn lcx_ccx(lcx: @local_ctxt) -> @crate_ctxt { ret lcx.ccx; }
446 pure fn ccx_tcx(ccx: @crate_ctxt) -> ty::ctxt { ret ccx.tcx; }
447
448 // LLVM type constructors.
449 fn T_void() -> TypeRef {
450     // Note: For the time being llvm is kinda busted here, it has the notion
451     // of a 'void' type that can only occur as part of the signature of a
452     // function, but no general unit type of 0-sized value. This is, afaict,
453     // vestigial from its C heritage, and we'll be attempting to submit a
454     // patch upstream to fix it. In the mean time we only model function
455     // outputs (Rust functions and C functions) using T_void, and model the
456     // Rust general purpose nil type you can construct as 1-bit (always
457     // zero). This makes the result incorrect for now -- things like a tuple
458     // of 10 nil values will have 10-bit size -- but it doesn't seem like we
459     // have any other options until it's fixed upstream.
460
461     ret llvm::LLVMVoidType();
462 }
463
464 fn T_nil() -> TypeRef {
465     // NB: See above in T_void().
466
467     ret llvm::LLVMInt1Type();
468 }
469
470 fn T_metadata() -> TypeRef { ret llvm::LLVMMetadataType(); }
471
472 fn T_i1() -> TypeRef { ret llvm::LLVMInt1Type(); }
473
474 fn T_i8() -> TypeRef { ret llvm::LLVMInt8Type(); }
475
476 fn T_i16() -> TypeRef { ret llvm::LLVMInt16Type(); }
477
478 fn T_i32() -> TypeRef { ret llvm::LLVMInt32Type(); }
479
480 fn T_i64() -> TypeRef { ret llvm::LLVMInt64Type(); }
481
482 fn T_f32() -> TypeRef { ret llvm::LLVMFloatType(); }
483
484 fn T_f64() -> TypeRef { ret llvm::LLVMDoubleType(); }
485
486 fn T_bool() -> TypeRef { ret T_i1(); }
487
488 fn T_int(targ_cfg: @session::config) -> TypeRef {
489     ret alt targ_cfg.arch {
490       session::arch_x86. { T_i32() }
491       session::arch_x86_64. { T_i64() }
492       session::arch_arm. { T_i32() }
493     };
494 }
495
496 fn T_int_ty(cx: @crate_ctxt, t: ast::int_ty) -> TypeRef {
497     alt t {
498       ast::ty_i. { cx.int_type }
499       ast::ty_char. { T_char() }
500       ast::ty_i8. { T_i8() }
501       ast::ty_i16. { T_i16() }
502       ast::ty_i32. { T_i32() }
503       ast::ty_i64. { T_i64() }
504     }
505 }
506
507 fn T_uint_ty(cx: @crate_ctxt, t: ast::uint_ty) -> TypeRef {
508     alt t {
509       ast::ty_u. { cx.int_type }
510       ast::ty_u8. { T_i8() }
511       ast::ty_u16. { T_i16() }
512       ast::ty_u32. { T_i32() }
513       ast::ty_u64. { T_i64() }
514     }
515 }
516
517 fn T_float_ty(cx: @crate_ctxt, t: ast::float_ty) -> TypeRef {
518     alt t {
519       ast::ty_f. { cx.float_type }
520       ast::ty_f32. { T_f32() }
521       ast::ty_f64. { T_f64() }
522     }
523 }
524
525 fn T_float(targ_cfg: @session::config) -> TypeRef {
526     ret alt targ_cfg.arch {
527       session::arch_x86. { T_f64() }
528       session::arch_x86_64. { T_f64() }
529       session::arch_arm. { T_f64() }
530     };
531 }
532
533 fn T_char() -> TypeRef { ret T_i32(); }
534
535 fn T_size_t(targ_cfg: @session::config) -> TypeRef {
536     ret T_int(targ_cfg);
537 }
538
539 fn T_fn(inputs: [TypeRef], output: TypeRef) -> TypeRef unsafe {
540     ret llvm::LLVMFunctionType(output, to_ptr(inputs),
541                                vec::len::<TypeRef>(inputs), False);
542 }
543
544 fn T_fn_pair(cx: @crate_ctxt, tfn: TypeRef) -> TypeRef {
545     ret T_struct([T_ptr(tfn), T_opaque_boxed_closure_ptr(cx)]);
546 }
547
548 fn T_ptr(t: TypeRef) -> TypeRef { ret llvm::LLVMPointerType(t, 0u); }
549
550 fn T_struct(elts: [TypeRef]) -> TypeRef unsafe {
551     ret llvm::LLVMStructType(to_ptr(elts), vec::len(elts), False);
552 }
553
554 fn T_named_struct(name: str) -> TypeRef {
555     let c = llvm::LLVMGetGlobalContext();
556     ret str::as_buf(name, {|buf| llvm::LLVMStructCreateNamed(c, buf) });
557 }
558
559 fn set_struct_body(t: TypeRef, elts: [TypeRef]) unsafe {
560     llvm::LLVMStructSetBody(t, to_ptr(elts), vec::len(elts), False);
561 }
562
563 fn T_empty_struct() -> TypeRef { ret T_struct([]); }
564
565 // NB: This will return something different every time it's called. If
566 // you need a generic object type that matches the type of your
567 // existing objects, use ccx.rust_object_type.  Calling
568 // T_rust_object() again will return a different one.
569 fn T_rust_object() -> TypeRef {
570     let t = T_named_struct("rust_object");
571     let e = T_ptr(T_empty_struct());
572     set_struct_body(t, [e, e]);
573     ret t;
574 }
575
576 // A dict is, in reality, a vtable pointer followed by zero or more pointers
577 // to tydescs and other dicts that it closes over. But the types and number of
578 // those are rarely known to the code that needs to manipulate them, so they
579 // are described by this opaque type.
580 fn T_dict() -> TypeRef { T_array(T_ptr(T_i8()), 1u) }
581
582 fn T_task(targ_cfg: @session::config) -> TypeRef {
583     let t = T_named_struct("task");
584
585     // Refcount
586     // Delegate pointer
587     // Stack segment pointer
588     // Runtime SP
589     // Rust SP
590     // GC chain
591
592
593     // Domain pointer
594     // Crate cache pointer
595
596     let t_int = T_int(targ_cfg);
597     let elems =
598         [t_int, t_int, t_int, t_int,
599          t_int, t_int, t_int, t_int];
600     set_struct_body(t, elems);
601     ret t;
602 }
603
604 fn T_tydesc_field(cx: @crate_ctxt, field: int) -> TypeRef unsafe {
605     // Bit of a kludge: pick the fn typeref out of the tydesc..
606
607     let tydesc_elts: [TypeRef] =
608         vec::init_elt::<TypeRef>(T_nil(),
609                                       abi::n_tydesc_fields as uint);
610     llvm::LLVMGetStructElementTypes(cx.tydesc_type,
611                                     to_ptr::<TypeRef>(tydesc_elts));
612     let t = llvm::LLVMGetElementType(tydesc_elts[field]);
613     ret t;
614 }
615
616 fn T_glue_fn(cx: @crate_ctxt) -> TypeRef {
617     let s = "glue_fn";
618     if cx.tn.name_has_type(s) { ret cx.tn.get_type(s); }
619     let t = T_tydesc_field(cx, abi::tydesc_field_drop_glue);
620     cx.tn.associate(s, t);
621     ret t;
622 }
623
624 fn T_cmp_glue_fn(cx: @crate_ctxt) -> TypeRef {
625     let s = "cmp_glue_fn";
626     if cx.tn.name_has_type(s) { ret cx.tn.get_type(s); }
627     let t = T_tydesc_field(cx, abi::tydesc_field_cmp_glue);
628     cx.tn.associate(s, t);
629     ret t;
630 }
631
632 fn T_tydesc(targ_cfg: @session::config) -> TypeRef {
633     let tydesc = T_named_struct("tydesc");
634     let tydescpp = T_ptr(T_ptr(tydesc));
635     let pvoid = T_ptr(T_i8());
636     let glue_fn_ty =
637         T_ptr(T_fn([T_ptr(T_nil()), T_ptr(T_nil()), tydescpp,
638                     pvoid], T_void()));
639     let cmp_glue_fn_ty =
640         T_ptr(T_fn([T_ptr(T_i1()), T_ptr(tydesc), tydescpp,
641                     pvoid, pvoid, T_i8()], T_void()));
642
643     let int_type = T_int(targ_cfg);
644     let elems =
645         [tydescpp, int_type, int_type,
646          glue_fn_ty, glue_fn_ty, glue_fn_ty,
647          T_ptr(T_i8()), glue_fn_ty, glue_fn_ty, glue_fn_ty, cmp_glue_fn_ty,
648          T_ptr(T_i8()), T_ptr(T_i8()), int_type, int_type];
649     set_struct_body(tydesc, elems);
650     ret tydesc;
651 }
652
653 fn T_array(t: TypeRef, n: uint) -> TypeRef { ret llvm::LLVMArrayType(t, n); }
654
655 // Interior vector.
656 //
657 // TODO: Support user-defined vector sizes.
658 fn T_vec2(targ_cfg: @session::config, t: TypeRef) -> TypeRef {
659     ret T_struct([T_int(targ_cfg), // fill
660                   T_int(targ_cfg), // alloc
661                   T_array(t, 0u)]); // elements
662 }
663
664 fn T_vec(ccx: @crate_ctxt, t: TypeRef) -> TypeRef {
665     ret T_vec2(ccx.sess.get_targ_cfg(), t);
666 }
667
668 // Note that the size of this one is in bytes.
669 fn T_opaque_vec(targ_cfg: @session::config) -> TypeRef {
670     ret T_vec2(targ_cfg, T_i8());
671 }
672
673 fn T_box(cx: @crate_ctxt, t: TypeRef) -> TypeRef {
674     ret T_struct([cx.int_type, t]);
675 }
676
677 fn T_port(cx: @crate_ctxt, _t: TypeRef) -> TypeRef {
678     ret T_struct([cx.int_type]); // Refcount
679
680 }
681
682 fn T_chan(cx: @crate_ctxt, _t: TypeRef) -> TypeRef {
683     ret T_struct([cx.int_type]); // Refcount
684
685 }
686
687 fn T_taskptr(cx: @crate_ctxt) -> TypeRef { ret T_ptr(cx.task_type); }
688
689
690 // This type must never be used directly; it must always be cast away.
691 fn T_typaram(tn: type_names) -> TypeRef {
692     let s = "typaram";
693     if tn.name_has_type(s) { ret tn.get_type(s); }
694     let t = T_i8();
695     tn.associate(s, t);
696     ret t;
697 }
698
699 fn T_typaram_ptr(tn: type_names) -> TypeRef { ret T_ptr(T_typaram(tn)); }
700
701 fn T_closure(cx: @crate_ctxt,
702              llbindings_ty: TypeRef,
703              n_ty_params: uint) -> TypeRef {
704     ret T_struct([T_ptr(cx.tydesc_type),
705                   T_captured_tydescs(cx, n_ty_params),
706                   llbindings_ty])
707 }
708
709 fn T_opaque_closure(cx: @crate_ctxt) -> TypeRef {
710     let s = "closure";
711     if cx.tn.name_has_type(s) { ret cx.tn.get_type(s); }
712     let t = T_closure(cx, T_nil(), 0u);
713     cx.tn.associate(s, t);
714     ret t;
715 }
716
717 fn T_boxed_closure_ptr(cx: @crate_ctxt, llbindings_ty: TypeRef,
718                      n_ty_params: uint) -> TypeRef {
719     // NB: keep this in sync with code in trans_bind; we're making
720     // an LLVM typeref structure that has the same "shape" as the ty::t
721     // it constructs.
722     ret T_ptr(T_box(cx, T_closure(cx, llbindings_ty, n_ty_params)));
723 }
724
725 fn T_opaque_boxed_closure_ptr(cx: @crate_ctxt) -> TypeRef {
726     let s = "*closure";
727     if cx.tn.name_has_type(s) { ret cx.tn.get_type(s); }
728     let t = T_boxed_closure_ptr(cx, T_nil(), 0u);
729     cx.tn.associate(s, t);
730     ret t;
731 }
732
733 fn T_tag_variant(cx: @crate_ctxt) -> TypeRef {
734     ret cx.int_type;
735 }
736
737 fn T_tag(cx: @crate_ctxt, size: uint) -> TypeRef {
738     let s = "tag_" + uint::to_str(size, 10u);
739     if cx.tn.name_has_type(s) { ret cx.tn.get_type(s); }
740     let t =
741         if size == 0u {
742             T_struct([T_tag_variant(cx)])
743         } else { T_struct([T_tag_variant(cx), T_array(T_i8(), size)]) };
744     cx.tn.associate(s, t);
745     ret t;
746 }
747
748 fn T_opaque_tag(cx: @crate_ctxt) -> TypeRef {
749     let s = "opaque_tag";
750     if cx.tn.name_has_type(s) { ret cx.tn.get_type(s); }
751     let t = T_struct([T_tag_variant(cx), T_i8()]);
752     cx.tn.associate(s, t);
753     ret t;
754 }
755
756 fn T_opaque_tag_ptr(cx: @crate_ctxt) -> TypeRef {
757     ret T_ptr(T_opaque_tag(cx));
758 }
759
760 fn T_captured_tydescs(cx: @crate_ctxt, n: uint) -> TypeRef {
761     ret T_struct(vec::init_elt::<TypeRef>(T_ptr(cx.tydesc_type), n));
762 }
763
764 fn T_obj_ptr(cx: @crate_ctxt, n_captured_tydescs: uint) -> TypeRef {
765     // This function is not publicly exposed because it returns an incomplete
766     // type. The dynamically-sized fields follow the captured tydescs.
767
768     fn T_obj(cx: @crate_ctxt, n_captured_tydescs: uint) -> TypeRef {
769         ret T_struct([T_ptr(cx.tydesc_type),
770                       T_captured_tydescs(cx, n_captured_tydescs)]);
771     }
772     ret T_ptr(T_box(cx, T_obj(cx, n_captured_tydescs)));
773 }
774
775 fn T_opaque_obj_ptr(cx: @crate_ctxt) -> TypeRef { ret T_obj_ptr(cx, 0u); }
776
777 fn T_opaque_port_ptr() -> TypeRef { ret T_ptr(T_i8()); }
778
779 fn T_opaque_chan_ptr() -> TypeRef { ret T_ptr(T_i8()); }
780
781
782 // LLVM constant constructors.
783 fn C_null(t: TypeRef) -> ValueRef { ret llvm::LLVMConstNull(t); }
784
785 fn C_integral(t: TypeRef, u: u64, sign_extend: Bool) -> ValueRef {
786     let u_hi = (u >> 32u64) as uint;
787     let u_lo = u as uint;
788     ret llvm::LLVMRustConstInt(t, u_hi, u_lo, sign_extend);
789 }
790
791 fn C_floating(s: str, t: TypeRef) -> ValueRef {
792     ret str::as_buf(s, {|buf| llvm::LLVMConstRealOfString(t, buf) });
793 }
794
795 fn C_nil() -> ValueRef {
796     // NB: See comment above in T_void().
797
798     ret C_integral(T_i1(), 0u64, False);
799 }
800
801 fn C_bool(b: bool) -> ValueRef {
802     if b {
803         ret C_integral(T_bool(), 1u64, False);
804     } else { ret C_integral(T_bool(), 0u64, False); }
805 }
806
807 fn C_i32(i: i32) -> ValueRef {
808     ret C_integral(T_i32(), i as u64, True);
809 }
810
811 fn C_i64(i: i64) -> ValueRef {
812     ret C_integral(T_i64(), i as u64, True);
813 }
814
815 fn C_int(cx: @crate_ctxt, i: int) -> ValueRef {
816     ret C_integral(cx.int_type, i as u64, True);
817 }
818
819 fn C_uint(cx: @crate_ctxt, i: uint) -> ValueRef {
820     ret C_integral(cx.int_type, i as u64, False);
821 }
822
823 fn C_u8(i: uint) -> ValueRef { ret C_integral(T_i8(), i as u64, False); }
824
825
826 // This is a 'c-like' raw string, which differs from
827 // our boxed-and-length-annotated strings.
828 fn C_cstr(cx: @crate_ctxt, s: str) -> ValueRef {
829     let sc =
830         str::as_buf(s,
831                     {|buf|
832                         llvm::LLVMConstString(buf, str::byte_len(s), False)
833                     });
834     let g =
835         str::as_buf(cx.names.next("str"),
836                     {|buf| llvm::LLVMAddGlobal(cx.llmod, val_ty(sc), buf) });
837     llvm::LLVMSetInitializer(g, sc);
838     llvm::LLVMSetGlobalConstant(g, True);
839     llvm::LLVMSetLinkage(g, lib::llvm::LLVMInternalLinkage as llvm::Linkage);
840     ret g;
841 }
842
843 // Returns a Plain Old LLVM String:
844 fn C_postr(s: str) -> ValueRef {
845     ret str::as_buf(s,
846                     {|buf|
847                         llvm::LLVMConstString(buf, str::byte_len(s), False)
848                     });
849 }
850
851 fn C_zero_byte_arr(size: uint) -> ValueRef unsafe {
852     let i = 0u;
853     let elts: [ValueRef] = [];
854     while i < size { elts += [C_u8(0u)]; i += 1u; }
855     ret llvm::LLVMConstArray(T_i8(), vec::to_ptr(elts),
856                              vec::len(elts));
857 }
858
859 fn C_struct(elts: [ValueRef]) -> ValueRef unsafe {
860     ret llvm::LLVMConstStruct(vec::to_ptr(elts), vec::len(elts),
861                               False);
862 }
863
864 fn C_named_struct(T: TypeRef, elts: [ValueRef]) -> ValueRef unsafe {
865     ret llvm::LLVMConstNamedStruct(T, vec::to_ptr(elts),
866                                    vec::len(elts));
867 }
868
869 fn C_array(ty: TypeRef, elts: [ValueRef]) -> ValueRef unsafe {
870     ret llvm::LLVMConstArray(ty, vec::to_ptr(elts),
871                              vec::len(elts));
872 }
873
874 fn C_bytes(bytes: [u8]) -> ValueRef unsafe {
875     ret llvm::LLVMConstString(
876         unsafe::reinterpret_cast(vec::to_ptr(bytes)),
877         vec::len(bytes), False);
878 }
879
880 fn C_shape(ccx: @crate_ctxt, bytes: [u8]) -> ValueRef {
881     let llshape = C_bytes(bytes);
882     let llglobal =
883         str::as_buf(ccx.names.next("shape"),
884                     {|buf|
885                         llvm::LLVMAddGlobal(ccx.llmod, val_ty(llshape), buf)
886                     });
887     llvm::LLVMSetInitializer(llglobal, llshape);
888     llvm::LLVMSetGlobalConstant(llglobal, True);
889     llvm::LLVMSetLinkage(llglobal,
890                          lib::llvm::LLVMInternalLinkage as llvm::Linkage);
891     ret llvm::LLVMConstPointerCast(llglobal, T_ptr(T_i8()));
892 }
893
894
895 pure fn valid_variant_index(ix: uint, cx: @block_ctxt, tag_id: ast::def_id,
896                             variant_id: ast::def_id) -> bool {
897
898     // Handwaving: it's ok to pretend this code is referentially
899     // transparent, because the relevant parts of the type context don't
900     // change. (We're not adding new variants during trans.)
901     unchecked{
902         let variant =
903             ty::tag_variant_with_id(bcx_tcx(cx), tag_id, variant_id);
904         ix < vec::len(variant.args)
905     }
906 }
907
908 pure fn type_has_static_size(cx: @crate_ctxt, t: ty::t) -> bool {
909     !ty::type_has_dynamic_size(cx.tcx, t)
910 }
911
912 pure fn non_ty_var(cx: @crate_ctxt, t: ty::t) -> bool {
913     let st = ty::struct(cx.tcx, t);
914     alt st {
915       ty::ty_var(_) { false }
916       _          { true }
917     }
918 }
919
920 pure fn returns_non_ty_var(cx: @crate_ctxt, t: ty::t) -> bool {
921     non_ty_var(cx, ty::ty_fn_ret(cx.tcx, t))
922 }
923
924 pure fn type_is_tup_like(cx: @block_ctxt, t: ty::t) -> bool {
925     let tcx = bcx_tcx(cx);
926     ty::type_is_tup_like(tcx, t)
927 }
928
929 // Used to identify cached dictionaries
930 tag dict_param {
931     dict_param_dict(dict_id);
932     dict_param_ty(ty::t);
933 }
934 type dict_id = @{impl_def: ast::def_id, params: [dict_param]};
935 fn hash_dict_id(&&dp: dict_id) -> uint {
936     let h = syntax::ast_util::hash_def_id(dp.impl_def);
937     for param in dp.params {
938         h = h << 2u;
939         alt param {
940           dict_param_dict(d) { h += hash_dict_id(d); }
941           dict_param_ty(t) { h += t; }
942         }
943     }
944     h
945 }
946
947 //
948 // Local Variables:
949 // mode: rust
950 // fill-column: 78;
951 // indent-tabs-mode: nil
952 // c-basic-offset: 4
953 // buffer-file-coding-system: utf-8-unix
954 // End:
955 //