about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEric Holk <eholk@mozilla.com>2011-07-14 17:08:22 -0700
committerEric Holk <eholk@mozilla.com>2011-07-14 17:08:45 -0700
commit8afb1a7c639d2d2959cdc79c544fac7dd5730897 (patch)
treef4a349131134cf40bbf394612e668685617531e5
parente2fcd29bbd7dc58b4af5f498cb1f323822ffc254 (diff)
downloadrust-8afb1a7c639d2d2959cdc79c544fac7dd5730897.tar.gz
rust-8afb1a7c639d2d2959cdc79c544fac7dd5730897.zip
refactor: Move the LLVM type and constant constructors into a new module.
-rw-r--r--src/comp/back/upcall.rs32
-rw-r--r--src/comp/middle/trans.rs428
-rw-r--r--src/comp/middle/trans_alt.rs9
-rw-r--r--src/comp/middle/trans_common.rs487
-rw-r--r--src/comp/rustc.rc1
5 files changed, 511 insertions, 446 deletions
diff --git a/src/comp/back/upcall.rs b/src/comp/back/upcall.rs
index 53a30999a5b..6d95b25b95b 100644
--- a/src/comp/back/upcall.rs
+++ b/src/comp/back/upcall.rs
@@ -1,22 +1,22 @@
 
 import middle::trans;
 import trans::decl_cdecl_fn;
-import trans::T_f32;
-import trans::T_f64;
-import trans::T_fn;
-import trans::T_bool;
-import trans::T_i8;
-import trans::T_i32;
-import trans::T_int;
-import trans::T_nil;
-import trans::T_opaque_chan_ptr;
-import trans::T_opaque_ivec;
-import trans::T_opaque_port_ptr;
-import trans::T_opaque_vec_ptr;
-import trans::T_ptr;
-import trans::T_size_t;
-import trans::T_str;
-import trans::T_void;
+import middle::trans_common::T_f32;
+import middle::trans_common::T_f64;
+import middle::trans_common::T_fn;
+import middle::trans_common::T_bool;
+import middle::trans_common::T_i8;
+import middle::trans_common::T_i32;
+import middle::trans_common::T_int;
+import middle::trans_common::T_nil;
+import middle::trans_common::T_opaque_chan_ptr;
+import middle::trans_common::T_opaque_ivec;
+import middle::trans_common::T_opaque_port_ptr;
+import middle::trans_common::T_opaque_vec_ptr;
+import middle::trans_common::T_ptr;
+import middle::trans_common::T_size_t;
+import middle::trans_common::T_str;
+import middle::trans_common::T_void;
 import lib::llvm::type_names;
 import lib::llvm::llvm::ModuleRef;
 import lib::llvm::llvm::ValueRef;
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index 5bedca727fd..fa107924546 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -65,6 +65,8 @@ import util::ppaux::ty_to_short_str;
 import syntax::print::pprust::expr_to_str;
 import syntax::print::pprust::path_to_str;
 
+import trans_common::*;
+
 obj namegen(mutable int i) {
     fn next(str prefix) -> str { i += 1; ret prefix + int::str(i); }
 }
@@ -399,330 +401,6 @@ fn struct_elt(TypeRef llstructty, uint n) -> TypeRef {
 }
 
 
-// LLVM type constructors.
-fn T_void() -> TypeRef {
-    // Note: For the time being llvm is kinda busted here, it has the notion
-    // of a 'void' type that can only occur as part of the signature of a
-    // function, but no general unit type of 0-sized value. This is, afaict,
-    // vestigial from its C heritage, and we'll be attempting to submit a
-    // patch upstream to fix it. In the mean time we only model function
-    // outputs (Rust functions and C functions) using T_void, and model the
-    // Rust general purpose nil type you can construct as 1-bit (always
-    // zero). This makes the result incorrect for now -- things like a tuple
-    // of 10 nil values will have 10-bit size -- but it doesn't seem like we
-    // have any other options until it's fixed upstream.
-
-    ret llvm::LLVMVoidType();
-}
-
-fn T_nil() -> TypeRef {
-    // NB: See above in T_void().
-
-    ret llvm::LLVMInt1Type();
-}
-
-fn T_i1() -> TypeRef { ret llvm::LLVMInt1Type(); }
-
-fn T_i8() -> TypeRef { ret llvm::LLVMInt8Type(); }
-
-fn T_i16() -> TypeRef { ret llvm::LLVMInt16Type(); }
-
-fn T_i32() -> TypeRef { ret llvm::LLVMInt32Type(); }
-
-fn T_i64() -> TypeRef { ret llvm::LLVMInt64Type(); }
-
-fn T_f32() -> TypeRef { ret llvm::LLVMFloatType(); }
-
-fn T_f64() -> TypeRef { ret llvm::LLVMDoubleType(); }
-
-fn T_bool() -> TypeRef { ret T_i1(); }
-
-fn T_int() -> TypeRef {
-    // FIXME: switch on target type.
-
-    ret T_i32();
-}
-
-fn T_float() -> TypeRef {
-    // FIXME: switch on target type.
-
-    ret T_f64();
-}
-
-fn T_char() -> TypeRef { ret T_i32(); }
-
-fn T_size_t() -> TypeRef {
-    // FIXME: switch on target type.
-
-    ret T_i32();
-}
-
-fn T_fn(&TypeRef[] inputs, TypeRef output) -> TypeRef {
-    ret llvm::LLVMFunctionType(output, std::ivec::to_ptr(inputs),
-                               std::ivec::len[TypeRef](inputs), False);
-}
-
-fn T_fn_pair(&crate_ctxt cx, TypeRef tfn) -> TypeRef {
-    ret T_struct(~[T_ptr(tfn), T_opaque_closure_ptr(cx)]);
-}
-
-fn T_ptr(TypeRef t) -> TypeRef { ret llvm::LLVMPointerType(t, 0u); }
-
-fn T_struct(&TypeRef[] elts) -> TypeRef {
-    ret llvm::LLVMStructType(std::ivec::to_ptr(elts), std::ivec::len(elts),
-                             False);
-}
-
-fn T_named_struct(&str name) -> TypeRef {
-    auto c = llvm::LLVMGetGlobalContext();
-    ret llvm::LLVMStructCreateNamed(c, str::buf(name));
-}
-
-fn set_struct_body(TypeRef t, &TypeRef[] elts) {
-    llvm::LLVMStructSetBody(t, std::ivec::to_ptr(elts), std::ivec::len(elts),
-                            False);
-}
-
-fn T_empty_struct() -> TypeRef { ret T_struct(~[]); }
-
-fn T_rust_object() -> TypeRef {
-    auto t = T_named_struct("rust_object");
-    auto e = T_ptr(T_empty_struct());
-    set_struct_body(t, ~[e,e]);
-    ret t;
-}
-
-fn T_task() -> TypeRef {
-    auto t = T_named_struct("task");
-
-    auto elems = ~[T_int(), // Refcount
-                   T_int(), // Delegate pointer
-                   T_int(), // Stack segment pointer
-                   T_int(), // Runtime SP
-                   T_int(), // Rust SP
-                   T_int(), // GC chain
-
-                   T_int(), // Domain pointer
-                            // Crate cache pointer
-                   T_int()];
-    set_struct_body(t, elems);
-    ret t;
-}
-
-fn T_tydesc_field(&crate_ctxt cx, int field) -> TypeRef {
-    // Bit of a kludge: pick the fn typeref out of the tydesc..
-
-    let TypeRef[] tydesc_elts =
-        std::ivec::init_elt[TypeRef](T_nil(), abi::n_tydesc_fields as uint);
-    llvm::LLVMGetStructElementTypes(cx.tydesc_type,
-                                    std::ivec::to_ptr[TypeRef](tydesc_elts));
-    auto t = llvm::LLVMGetElementType(tydesc_elts.(field));
-    ret t;
-}
-
-fn T_glue_fn(&crate_ctxt cx) -> TypeRef {
-    auto s = "glue_fn";
-    if (cx.tn.name_has_type(s)) { ret cx.tn.get_type(s); }
-    auto t = T_tydesc_field(cx, abi::tydesc_field_drop_glue);
-    cx.tn.associate(s, t);
-    ret t;
-}
-
-fn T_dtor(&@crate_ctxt ccx, &span sp) -> TypeRef {
-    ret type_of_fn_full(ccx, sp, ast::proto_fn, true,
-                        ~[], ty::mk_nil(ccx.tcx), 0u);
-}
-
-fn T_cmp_glue_fn(&crate_ctxt cx) -> TypeRef {
-    auto s = "cmp_glue_fn";
-    if (cx.tn.name_has_type(s)) { ret cx.tn.get_type(s); }
-    auto t = T_tydesc_field(cx, abi::tydesc_field_cmp_glue);
-    cx.tn.associate(s, t);
-    ret t;
-}
-
-fn T_tydesc(TypeRef taskptr_type) -> TypeRef {
-    auto tydesc = T_named_struct("tydesc");
-    auto tydescpp = T_ptr(T_ptr(tydesc));
-    auto pvoid = T_ptr(T_i8());
-    auto glue_fn_ty =
-        T_ptr(T_fn(~[T_ptr(T_nil()), taskptr_type, T_ptr(T_nil()), tydescpp,
-                     pvoid], T_void()));
-    auto cmp_glue_fn_ty =
-        T_ptr(T_fn(~[T_ptr(T_i1()), taskptr_type, T_ptr(T_nil()), tydescpp,
-                     pvoid, pvoid, T_i8()], T_void()));
-
-    auto elems = ~[tydescpp,   // first_param
-                   T_int(),    // size
-                   T_int(),    // align
-                   glue_fn_ty, // copy_glue
-                   glue_fn_ty, // drop_glue
-                   glue_fn_ty, // free_glue
-                   glue_fn_ty, // sever_glue
-                   glue_fn_ty, // mark_glue
-                   glue_fn_ty, // obj_drop_glue
-                   glue_fn_ty, // is_stateful
-                   cmp_glue_fn_ty];
-    set_struct_body(tydesc, elems);
-    ret tydesc;
-}
-
-fn T_array(TypeRef t, uint n) -> TypeRef { ret llvm::LLVMArrayType(t, n); }
-
-fn T_vec(TypeRef t) -> TypeRef {
-    ret T_struct(~[T_int(), // Refcount
-                   T_int(), // Alloc
-                   T_int(), // Fill
-
-                   T_int(), // Pad
-                           // Body elements
-                            T_array(t, 0u)]);
-}
-
-fn T_opaque_vec_ptr() -> TypeRef { ret T_ptr(T_vec(T_int())); }
-
-
-// Interior vector.
-//
-// TODO: Support user-defined vector sizes.
-fn T_ivec(TypeRef t) -> TypeRef {
-    ret T_struct(~[T_int(), // Length ("fill"; if zero, heapified)
-                   T_int(), // Alloc
-                   T_array(t, abi::ivec_default_length)]); // Body elements
-
-}
-
-
-// Note that the size of this one is in bytes.
-fn T_opaque_ivec() -> TypeRef {
-    ret T_struct(~[T_int(), // Length ("fill"; if zero, heapified)
-                   T_int(), // Alloc
-                   T_array(T_i8(), 0u)]); // Body elements
-
-}
-
-fn T_ivec_heap_part(TypeRef t) -> TypeRef {
-    ret T_struct(~[T_int(), // Real length
-                   T_array(t, 0u)]); // Body elements
-
-}
-
-
-// Interior vector on the heap, also known as the "stub". Cast to this when
-// the allocated length (second element of T_ivec above) is zero.
-fn T_ivec_heap(TypeRef t) -> TypeRef {
-    ret T_struct(~[T_int(), // Length (zero)
-                   T_int(), // Alloc
-                   T_ptr(T_ivec_heap_part(t))]); // Pointer
-
-}
-
-fn T_opaque_ivec_heap_part() -> TypeRef {
-    ret T_struct(~[T_int(), // Real length
-                   T_array(T_i8(), 0u)]); // Body elements
-
-}
-
-fn T_opaque_ivec_heap() -> TypeRef {
-    ret T_struct(~[T_int(), // Length (zero)
-                   T_int(), // Alloc
-                   T_ptr(T_opaque_ivec_heap_part())]); // Pointer
-
-}
-
-fn T_str() -> TypeRef { ret T_vec(T_i8()); }
-
-fn T_box(TypeRef t) -> TypeRef { ret T_struct(~[T_int(), t]); }
-
-fn T_port(TypeRef t) -> TypeRef {
-    ret T_struct(~[T_int()]); // Refcount
-
-}
-
-fn T_chan(TypeRef t) -> TypeRef {
-    ret T_struct(~[T_int()]); // Refcount
-
-}
-
-fn T_taskptr(&crate_ctxt cx) -> TypeRef { ret T_ptr(cx.task_type); }
-
-
-// This type must never be used directly; it must always be cast away.
-fn T_typaram(&type_names tn) -> TypeRef {
-    auto s = "typaram";
-    if (tn.name_has_type(s)) { ret tn.get_type(s); }
-    auto t = T_i8();
-    tn.associate(s, t);
-    ret t;
-}
-
-fn T_typaram_ptr(&type_names tn) -> TypeRef { ret T_ptr(T_typaram(tn)); }
-
-fn T_closure_ptr(&crate_ctxt cx, TypeRef lltarget_ty, TypeRef llbindings_ty,
-                 uint n_ty_params) -> TypeRef {
-    // NB: keep this in sync with code in trans_bind; we're making
-    // an LLVM typeref structure that has the same "shape" as the ty::t
-    // it constructs.
-
-    ret T_ptr(T_box(T_struct(~[T_ptr(cx.tydesc_type), lltarget_ty,
-                               llbindings_ty,
-                               T_captured_tydescs(cx, n_ty_params)])));
-}
-
-fn T_opaque_closure_ptr(&crate_ctxt cx) -> TypeRef {
-    auto s = "*closure";
-    if (cx.tn.name_has_type(s)) { ret cx.tn.get_type(s); }
-    auto t =
-        T_closure_ptr(cx,
-                      T_struct(~[T_ptr(T_nil()), T_ptr(T_nil())]),
-                      T_nil(),
-                      0u);
-    cx.tn.associate(s, t);
-    ret t;
-}
-
-fn T_tag(&type_names tn, uint size) -> TypeRef {
-    auto s = "tag_" + uint::to_str(size, 10u);
-    if (tn.name_has_type(s)) { ret tn.get_type(s); }
-    auto t = T_struct(~[T_int(), T_array(T_i8(), size)]);
-    tn.associate(s, t);
-    ret t;
-}
-
-fn T_opaque_tag(&type_names tn) -> TypeRef {
-    auto s = "opaque_tag";
-    if (tn.name_has_type(s)) { ret tn.get_type(s); }
-    auto t = T_struct(~[T_int(), T_i8()]);
-    tn.associate(s, t);
-    ret t;
-}
-
-fn T_opaque_tag_ptr(&type_names tn) -> TypeRef {
-    ret T_ptr(T_opaque_tag(tn));
-}
-
-fn T_captured_tydescs(&crate_ctxt cx, uint n) -> TypeRef {
-    ret T_struct(std::ivec::init_elt[TypeRef](T_ptr(cx.tydesc_type), n));
-}
-
-fn T_obj_ptr(&crate_ctxt cx, uint n_captured_tydescs) -> TypeRef {
-    // This function is not publicly exposed because it returns an incomplete
-    // type. The dynamically-sized fields follow the captured tydescs.
-
-    fn T_obj(&crate_ctxt cx, uint n_captured_tydescs) -> TypeRef {
-        ret T_struct(~[T_ptr(cx.tydesc_type),
-                       T_captured_tydescs(cx, n_captured_tydescs)]);
-    }
-    ret T_ptr(T_box(T_obj(cx, n_captured_tydescs)));
-}
-
-fn T_opaque_obj_ptr(&crate_ctxt cx) -> TypeRef { ret T_obj_ptr(cx, 0u); }
-
-fn T_opaque_port_ptr() -> TypeRef { ret T_ptr(T_i8()); }
-
-fn T_opaque_chan_ptr() -> TypeRef { ret T_ptr(T_i8()); }
-
-
 // This function now fails if called on a type with dynamic size (as its
 // return value was always meaningless in that case anyhow). Beware!
 //
@@ -1009,106 +687,6 @@ fn sanitize(&str s) -> str {
 }
 
 
-// LLVM constant constructors.
-fn C_null(TypeRef t) -> ValueRef { ret llvm::LLVMConstNull(t); }
-
-fn C_integral(TypeRef t, uint u, Bool sign_extend) -> ValueRef {
-    // FIXME: We can't use LLVM::ULongLong with our existing minimal native
-    // API, which only knows word-sized args.
-    //
-    // ret llvm::LLVMConstInt(T_int(), t as LLVM::ULongLong, False);
-    //
-
-    ret llvm::LLVMRustConstSmallInt(t, u, sign_extend);
-}
-
-fn C_float(&str s) -> ValueRef {
-    ret llvm::LLVMConstRealOfString(T_float(), str::buf(s));
-}
-
-fn C_floating(&str s, TypeRef t) -> ValueRef {
-    ret llvm::LLVMConstRealOfString(t, str::buf(s));
-}
-
-fn C_nil() -> ValueRef {
-    // NB: See comment above in T_void().
-
-    ret C_integral(T_i1(), 0u, False);
-}
-
-fn C_bool(bool b) -> ValueRef {
-    if (b) {
-        ret C_integral(T_bool(), 1u, False);
-    } else { ret C_integral(T_bool(), 0u, False); }
-}
-
-fn C_int(int i) -> ValueRef { ret C_integral(T_int(), i as uint, True); }
-
-fn C_uint(uint i) -> ValueRef { ret C_integral(T_int(), i, False); }
-
-fn C_u8(uint i) -> ValueRef { ret C_integral(T_i8(), i, False); }
-
-
-// This is a 'c-like' raw string, which differs from
-// our boxed-and-length-annotated strings.
-fn C_cstr(&@crate_ctxt cx, &str s) -> ValueRef {
-    auto sc = llvm::LLVMConstString(str::buf(s), str::byte_len(s), False);
-    auto g =
-        llvm::LLVMAddGlobal(cx.llmod, val_ty(sc),
-                            str::buf(cx.names.next("str")));
-    llvm::LLVMSetInitializer(g, sc);
-    llvm::LLVMSetGlobalConstant(g, True);
-    llvm::LLVMSetLinkage(g, lib::llvm::LLVMInternalLinkage as llvm::Linkage);
-    ret g;
-}
-
-
-// A rust boxed-and-length-annotated string.
-fn C_str(&@crate_ctxt cx, &str s) -> ValueRef {
-    auto len = str::byte_len(s);
-    auto box =
-        C_struct(~[C_int(abi::const_refcount as int),
-                   C_int(len + 1u as int), // 'alloc'
-                   C_int(len + 1u as int), // 'fill'
-                   C_int(0), // 'pad'
-                   llvm::LLVMConstString(str::buf(s), len, False)]);
-    auto g =
-        llvm::LLVMAddGlobal(cx.llmod, val_ty(box),
-                            str::buf(cx.names.next("str")));
-    llvm::LLVMSetInitializer(g, box);
-    llvm::LLVMSetGlobalConstant(g, True);
-    llvm::LLVMSetLinkage(g, lib::llvm::LLVMInternalLinkage as llvm::Linkage);
-    ret llvm::LLVMConstPointerCast(g, T_ptr(T_str()));
-}
-
-// Returns a Plain Old LLVM String:
-fn C_postr(&str s) -> ValueRef {
-    ret llvm::LLVMConstString(str::buf(s), str::byte_len(s), False);
-}
-
-fn C_zero_byte_arr(uint size) -> ValueRef {
-    auto i = 0u;
-    let ValueRef[] elts = ~[];
-    while (i < size) { elts += ~[C_u8(0u)]; i += 1u; }
-    ret llvm::LLVMConstArray(T_i8(), std::ivec::to_ptr(elts),
-                             std::ivec::len(elts));
-}
-
-fn C_struct(&ValueRef[] elts) -> ValueRef {
-    ret llvm::LLVMConstStruct(std::ivec::to_ptr(elts), std::ivec::len(elts),
-                              False);
-}
-
-fn C_named_struct(TypeRef T, &ValueRef[] elts) -> ValueRef {
-    ret llvm::LLVMConstNamedStruct(T, std::ivec::to_ptr(elts),
-                                   std::ivec::len(elts));
-}
-
-fn C_array(TypeRef ty, &ValueRef[] elts) -> ValueRef {
-    ret llvm::LLVMConstArray(ty, std::ivec::to_ptr(elts),
-                             std::ivec::len(elts));
-}
-
 fn decl_fn(ModuleRef llmod, &str name, uint cc, TypeRef llty) -> ValueRef {
     let ValueRef llfn = llvm::LLVMAddFunction(llmod, str::buf(name), llty);
     llvm::LLVMSetFunctionCallConv(llfn, cc);
@@ -9250,7 +8828,7 @@ fn create_crate_map(&@crate_ctxt ccx) -> ValueRef {
 fn write_metadata(&@trans::crate_ctxt cx, &@ast::crate crate) {
     if (!cx.sess.get_opts().library) { ret; }
     auto llmeta = C_postr(metadata::encoder::encode_metadata(cx, crate));
-    auto llconst = trans::C_struct(~[llmeta]);
+    auto llconst = trans_common::C_struct(~[llmeta]);
     auto llglobal =
         llvm::LLVMAddGlobal(cx.llmod, trans::val_ty(llconst),
                             str::buf("rust_metadata"));
diff --git a/src/comp/middle/trans_alt.rs b/src/comp/middle/trans_alt.rs
index 9bd453943fb..bc9a7fe235c 100644
--- a/src/comp/middle/trans_alt.rs
+++ b/src/comp/middle/trans_alt.rs
@@ -16,9 +16,6 @@ import trans::block_ctxt;
 import trans::new_sub_block_ctxt;
 import trans::new_scope_block_ctxt;
 import trans::load_if_immediate;
-import trans::C_int;
-import trans::C_uint;
-import trans::C_nil;
 import trans::val_ty;
 import ty::pat_ty;
 import syntax::ast;
@@ -26,6 +23,8 @@ import syntax::ast::def_id;
 import syntax::codemap::span;
 import util::common::lit_eq;
 
+import trans_common::*;
+
 // An option identifying a branch (either a literal or a tag variant)
 tag opt {
     lit(@ast::lit);
@@ -201,7 +200,7 @@ fn extract_variant_args(@block_ctxt bcx, ast::node_id pat_id,
                           (ccx.tcx, vdefs._0, vdefs._1).args);
     if (size > 0u && ivec::len(variants) != 1u) {
         auto tagptr = bcx.build.PointerCast
-            (val, trans::T_opaque_tag_ptr(ccx.tn));
+            (val, trans_common::T_opaque_tag_ptr(ccx.tn));
         blobptr = bcx.build.GEP(tagptr, ~[C_int(0), C_int(1)]);
     }
     auto i = 0u;
@@ -315,7 +314,7 @@ fn compile_submatch(@block_ctxt bcx, &match m, ValueRef[] vals, &mk_fail f,
                     kind = single;
                 } else {
                     auto tagptr = bcx.build.PointerCast
-                        (val, trans::T_opaque_tag_ptr(ccx.tn));
+                        (val, trans_common::T_opaque_tag_ptr(ccx.tn));
                     auto discrimptr = bcx.build.GEP
                         (tagptr, ~[C_int(0), C_int(0)]);
                     test_val = bcx.build.Load(discrimptr);
diff --git a/src/comp/middle/trans_common.rs b/src/comp/middle/trans_common.rs
new file mode 100644
index 00000000000..65c1bfb956e
--- /dev/null
+++ b/src/comp/middle/trans_common.rs
@@ -0,0 +1,487 @@
+/**
+   Code that is useful in various trans modules.
+
+*/
+
+import std::int;
+import std::str;
+import std::uint;
+import std::str::rustrt::sbuf;
+import std::map;
+import std::map::hashmap;
+import std::option;
+import std::option::some;
+import std::option::none;
+import std::fs;
+import syntax::ast;
+import syntax::walk;
+import driver::session;
+import middle::ty;
+import back::link;
+import back::x86;
+import back::abi;
+import back::upcall;
+import syntax::visit;
+import visit::vt;
+import util::common;
+import util::common::*;
+import std::map::new_int_hash;
+import std::map::new_str_hash;
+import syntax::codemap::span;
+import lib::llvm::llvm;
+import lib::llvm::builder;
+import lib::llvm::target_data;
+import lib::llvm::type_names;
+import lib::llvm::mk_target_data;
+import lib::llvm::mk_type_names;
+import lib::llvm::llvm::ModuleRef;
+import lib::llvm::llvm::ValueRef;
+import lib::llvm::llvm::TypeRef;
+import lib::llvm::llvm::TypeHandleRef;
+import lib::llvm::llvm::BuilderRef;
+import lib::llvm::llvm::BasicBlockRef;
+import lib::llvm::False;
+import lib::llvm::True;
+import lib::llvm::Bool;
+import link::mangle_internal_name_by_type_only;
+import link::mangle_internal_name_by_seq;
+import link::mangle_internal_name_by_path;
+import link::mangle_internal_name_by_path_and_seq;
+import link::mangle_exported_name;
+import metadata::creader;
+import metadata::csearch;
+import metadata::cstore;
+import util::ppaux::ty_to_str;
+import util::ppaux::ty_to_short_str;
+import syntax::print::pprust::expr_to_str;
+import syntax::print::pprust::path_to_str;
+
+// FIXME: These should probably be pulled in here too.
+import trans::crate_ctxt;
+import trans::type_of_fn_full;
+import trans::val_ty;
+
+// LLVM type constructors.
+fn T_void() -> TypeRef {
+    // Note: For the time being llvm is kinda busted here, it has the notion
+    // of a 'void' type that can only occur as part of the signature of a
+    // function, but no general unit type of 0-sized value. This is, afaict,
+    // vestigial from its C heritage, and we'll be attempting to submit a
+    // patch upstream to fix it. In the mean time we only model function
+    // outputs (Rust functions and C functions) using T_void, and model the
+    // Rust general purpose nil type you can construct as 1-bit (always
+    // zero). This makes the result incorrect for now -- things like a tuple
+    // of 10 nil values will have 10-bit size -- but it doesn't seem like we
+    // have any other options until it's fixed upstream.
+
+    ret llvm::LLVMVoidType();
+}
+
+fn T_nil() -> TypeRef {
+    // NB: See above in T_void().
+
+    ret llvm::LLVMInt1Type();
+}
+
+fn T_i1() -> TypeRef { ret llvm::LLVMInt1Type(); }
+
+fn T_i8() -> TypeRef { ret llvm::LLVMInt8Type(); }
+
+fn T_i16() -> TypeRef { ret llvm::LLVMInt16Type(); }
+
+fn T_i32() -> TypeRef { ret llvm::LLVMInt32Type(); }
+
+fn T_i64() -> TypeRef { ret llvm::LLVMInt64Type(); }
+
+fn T_f32() -> TypeRef { ret llvm::LLVMFloatType(); }
+
+fn T_f64() -> TypeRef { ret llvm::LLVMDoubleType(); }
+
+fn T_bool() -> TypeRef { ret T_i1(); }
+
+fn T_int() -> TypeRef {
+    // FIXME: switch on target type.
+
+    ret T_i32();
+}
+
+fn T_float() -> TypeRef {
+    // FIXME: switch on target type.
+
+    ret T_f64();
+}
+
+fn T_char() -> TypeRef { ret T_i32(); }
+
+fn T_size_t() -> TypeRef {
+    // FIXME: switch on target type.
+
+    ret T_i32();
+}
+
+fn T_fn(&TypeRef[] inputs, TypeRef output) -> TypeRef {
+    ret llvm::LLVMFunctionType(output, std::ivec::to_ptr(inputs),
+                               std::ivec::len[TypeRef](inputs), False);
+}
+
+fn T_fn_pair(&crate_ctxt cx, TypeRef tfn) -> TypeRef {
+    ret T_struct(~[T_ptr(tfn), T_opaque_closure_ptr(cx)]);
+}
+
+fn T_ptr(TypeRef t) -> TypeRef { ret llvm::LLVMPointerType(t, 0u); }
+
+fn T_struct(&TypeRef[] elts) -> TypeRef {
+    ret llvm::LLVMStructType(std::ivec::to_ptr(elts), std::ivec::len(elts),
+                             False);
+}
+
+fn T_named_struct(&str name) -> TypeRef {
+    auto c = llvm::LLVMGetGlobalContext();
+    ret llvm::LLVMStructCreateNamed(c, str::buf(name));
+}
+
+fn set_struct_body(TypeRef t, &TypeRef[] elts) {
+    llvm::LLVMStructSetBody(t, std::ivec::to_ptr(elts), std::ivec::len(elts),
+                            False);
+}
+
+fn T_empty_struct() -> TypeRef { ret T_struct(~[]); }
+
+fn T_rust_object() -> TypeRef {
+    auto t = T_named_struct("rust_object");
+    auto e = T_ptr(T_empty_struct());
+    set_struct_body(t, ~[e,e]);
+    ret t;
+}
+
+fn T_task() -> TypeRef {
+    auto t = T_named_struct("task");
+
+    auto elems = ~[T_int(), // Refcount
+                   T_int(), // Delegate pointer
+                   T_int(), // Stack segment pointer
+                   T_int(), // Runtime SP
+                   T_int(), // Rust SP
+                   T_int(), // GC chain
+
+                   T_int(), // Domain pointer
+                            // Crate cache pointer
+                   T_int()];
+    set_struct_body(t, elems);
+    ret t;
+}
+
+fn T_tydesc_field(&crate_ctxt cx, int field) -> TypeRef {
+    // Bit of a kludge: pick the fn typeref out of the tydesc..
+
+    let TypeRef[] tydesc_elts =
+        std::ivec::init_elt[TypeRef](T_nil(), abi::n_tydesc_fields as uint);
+    llvm::LLVMGetStructElementTypes(cx.tydesc_type,
+                                    std::ivec::to_ptr[TypeRef](tydesc_elts));
+    auto t = llvm::LLVMGetElementType(tydesc_elts.(field));
+    ret t;
+}
+
+fn T_glue_fn(&crate_ctxt cx) -> TypeRef {
+    auto s = "glue_fn";
+    if (cx.tn.name_has_type(s)) { ret cx.tn.get_type(s); }
+    auto t = T_tydesc_field(cx, abi::tydesc_field_drop_glue);
+    cx.tn.associate(s, t);
+    ret t;
+}
+
+fn T_dtor(&@crate_ctxt ccx, &span sp) -> TypeRef {
+    ret type_of_fn_full(ccx, sp, ast::proto_fn, true,
+                        ~[], ty::mk_nil(ccx.tcx), 0u);
+}
+
+fn T_cmp_glue_fn(&crate_ctxt cx) -> TypeRef {
+    auto s = "cmp_glue_fn";
+    if (cx.tn.name_has_type(s)) { ret cx.tn.get_type(s); }
+    auto t = T_tydesc_field(cx, abi::tydesc_field_cmp_glue);
+    cx.tn.associate(s, t);
+    ret t;
+}
+
+fn T_tydesc(TypeRef taskptr_type) -> TypeRef {
+    auto tydesc = T_named_struct("tydesc");
+    auto tydescpp = T_ptr(T_ptr(tydesc));
+    auto pvoid = T_ptr(T_i8());
+    auto glue_fn_ty =
+        T_ptr(T_fn(~[T_ptr(T_nil()), taskptr_type, T_ptr(T_nil()), tydescpp,
+                     pvoid], T_void()));
+    auto cmp_glue_fn_ty =
+        T_ptr(T_fn(~[T_ptr(T_i1()), taskptr_type, T_ptr(T_nil()), tydescpp,
+                     pvoid, pvoid, T_i8()], T_void()));
+
+    auto elems = ~[tydescpp,   // first_param
+                   T_int(),    // size
+                   T_int(),    // align
+                   glue_fn_ty, // copy_glue
+                   glue_fn_ty, // drop_glue
+                   glue_fn_ty, // free_glue
+                   glue_fn_ty, // sever_glue
+                   glue_fn_ty, // mark_glue
+                   glue_fn_ty, // obj_drop_glue
+                   glue_fn_ty, // is_stateful
+                   cmp_glue_fn_ty];
+    set_struct_body(tydesc, elems);
+    ret tydesc;
+}
+
+fn T_array(TypeRef t, uint n) -> TypeRef { ret llvm::LLVMArrayType(t, n); }
+
+fn T_vec(TypeRef t) -> TypeRef {
+    ret T_struct(~[T_int(), // Refcount
+                   T_int(), // Alloc
+                   T_int(), // Fill
+
+                   T_int(), // Pad
+                           // Body elements
+                            T_array(t, 0u)]);
+}
+
+fn T_opaque_vec_ptr() -> TypeRef { ret T_ptr(T_vec(T_int())); }
+
+
+// Interior vector.
+//
+// TODO: Support user-defined vector sizes.
+fn T_ivec(TypeRef t) -> TypeRef {
+    ret T_struct(~[T_int(), // Length ("fill"; if zero, heapified)
+                   T_int(), // Alloc
+                   T_array(t, abi::ivec_default_length)]); // Body elements
+
+}
+
+
+// Note that the size of this one is in bytes.
+fn T_opaque_ivec() -> TypeRef {
+    ret T_struct(~[T_int(), // Length ("fill"; if zero, heapified)
+                   T_int(), // Alloc
+                   T_array(T_i8(), 0u)]); // Body elements
+
+}
+
+fn T_ivec_heap_part(TypeRef t) -> TypeRef {
+    ret T_struct(~[T_int(), // Real length
+                   T_array(t, 0u)]); // Body elements
+
+}
+
+
+// Interior vector on the heap, also known as the "stub". Cast to this when
+// the allocated length (second element of T_ivec above) is zero.
+fn T_ivec_heap(TypeRef t) -> TypeRef {
+    ret T_struct(~[T_int(), // Length (zero)
+                   T_int(), // Alloc
+                   T_ptr(T_ivec_heap_part(t))]); // Pointer
+
+}
+
+fn T_opaque_ivec_heap_part() -> TypeRef {
+    ret T_struct(~[T_int(), // Real length
+                   T_array(T_i8(), 0u)]); // Body elements
+
+}
+
+fn T_opaque_ivec_heap() -> TypeRef {
+    ret T_struct(~[T_int(), // Length (zero)
+                   T_int(), // Alloc
+                   T_ptr(T_opaque_ivec_heap_part())]); // Pointer
+
+}
+
+fn T_str() -> TypeRef { ret T_vec(T_i8()); }
+
+fn T_box(TypeRef t) -> TypeRef { ret T_struct(~[T_int(), t]); }
+
+fn T_port(TypeRef t) -> TypeRef {
+    ret T_struct(~[T_int()]); // Refcount
+
+}
+
+fn T_chan(TypeRef t) -> TypeRef {
+    ret T_struct(~[T_int()]); // Refcount
+
+}
+
+fn T_taskptr(&crate_ctxt cx) -> TypeRef { ret T_ptr(cx.task_type); }
+
+
+// This type must never be used directly; it must always be cast away.
+fn T_typaram(&type_names tn) -> TypeRef {
+    auto s = "typaram";
+    if (tn.name_has_type(s)) { ret tn.get_type(s); }
+    auto t = T_i8();
+    tn.associate(s, t);
+    ret t;
+}
+
+fn T_typaram_ptr(&type_names tn) -> TypeRef { ret T_ptr(T_typaram(tn)); }
+
+fn T_closure_ptr(&crate_ctxt cx, TypeRef lltarget_ty, TypeRef llbindings_ty,
+                 uint n_ty_params) -> TypeRef {
+    // NB: keep this in sync with code in trans_bind; we're making
+    // an LLVM typeref structure that has the same "shape" as the ty::t
+    // it constructs.
+
+    ret T_ptr(T_box(T_struct(~[T_ptr(cx.tydesc_type), lltarget_ty,
+                               llbindings_ty,
+                               T_captured_tydescs(cx, n_ty_params)])));
+}
+
+fn T_opaque_closure_ptr(&crate_ctxt cx) -> TypeRef {
+    auto s = "*closure";
+    if (cx.tn.name_has_type(s)) { ret cx.tn.get_type(s); }
+    auto t =
+        T_closure_ptr(cx,
+                      T_struct(~[T_ptr(T_nil()), T_ptr(T_nil())]),
+                      T_nil(),
+                      0u);
+    cx.tn.associate(s, t);
+    ret t;
+}
+
+fn T_tag(&type_names tn, uint size) -> TypeRef {
+    auto s = "tag_" + uint::to_str(size, 10u);
+    if (tn.name_has_type(s)) { ret tn.get_type(s); }
+    auto t = T_struct(~[T_int(), T_array(T_i8(), size)]);
+    tn.associate(s, t);
+    ret t;
+}
+
+fn T_opaque_tag(&type_names tn) -> TypeRef {
+    auto s = "opaque_tag";
+    if (tn.name_has_type(s)) { ret tn.get_type(s); }
+    auto t = T_struct(~[T_int(), T_i8()]);
+    tn.associate(s, t);
+    ret t;
+}
+
+fn T_opaque_tag_ptr(&type_names tn) -> TypeRef {
+    ret T_ptr(T_opaque_tag(tn));
+}
+
+fn T_captured_tydescs(&crate_ctxt cx, uint n) -> TypeRef {
+    ret T_struct(std::ivec::init_elt[TypeRef](T_ptr(cx.tydesc_type), n));
+}
+
+fn T_obj_ptr(&crate_ctxt cx, uint n_captured_tydescs) -> TypeRef {
+    // This function is not publicly exposed because it returns an incomplete
+    // type. The dynamically-sized fields follow the captured tydescs.
+
+    fn T_obj(&crate_ctxt cx, uint n_captured_tydescs) -> TypeRef {
+        ret T_struct(~[T_ptr(cx.tydesc_type),
+                       T_captured_tydescs(cx, n_captured_tydescs)]);
+    }
+    ret T_ptr(T_box(T_obj(cx, n_captured_tydescs)));
+}
+
+fn T_opaque_obj_ptr(&crate_ctxt cx) -> TypeRef { ret T_obj_ptr(cx, 0u); }
+
+fn T_opaque_port_ptr() -> TypeRef { ret T_ptr(T_i8()); }
+
+fn T_opaque_chan_ptr() -> TypeRef { ret T_ptr(T_i8()); }
+
+
+// LLVM constant constructors.
+fn C_null(TypeRef t) -> ValueRef { ret llvm::LLVMConstNull(t); }
+
+fn C_integral(TypeRef t, uint u, Bool sign_extend) -> ValueRef {
+    // FIXME: We can't use LLVM::ULongLong with our existing minimal native
+    // API, which only knows word-sized args.
+    //
+    // ret llvm::LLVMConstInt(T_int(), t as LLVM::ULongLong, False);
+    //
+
+    ret llvm::LLVMRustConstSmallInt(t, u, sign_extend);
+}
+
+fn C_float(&str s) -> ValueRef {
+    ret llvm::LLVMConstRealOfString(T_float(), str::buf(s));
+}
+
+fn C_floating(&str s, TypeRef t) -> ValueRef {
+    ret llvm::LLVMConstRealOfString(t, str::buf(s));
+}
+
+fn C_nil() -> ValueRef {
+    // NB: See comment above in T_void().
+
+    ret C_integral(T_i1(), 0u, False);
+}
+
+fn C_bool(bool b) -> ValueRef {
+    if (b) {
+        ret C_integral(T_bool(), 1u, False);
+    } else { ret C_integral(T_bool(), 0u, False); }
+}
+
+fn C_int(int i) -> ValueRef { ret C_integral(T_int(), i as uint, True); }
+
+fn C_uint(uint i) -> ValueRef { ret C_integral(T_int(), i, False); }
+
+fn C_u8(uint i) -> ValueRef { ret C_integral(T_i8(), i, False); }
+
+
+// This is a 'c-like' raw string, which differs from
+// our boxed-and-length-annotated strings.
+fn C_cstr(&@crate_ctxt cx, &str s) -> ValueRef {
+    auto sc = llvm::LLVMConstString(str::buf(s), str::byte_len(s), False);
+    auto g =
+        llvm::LLVMAddGlobal(cx.llmod, val_ty(sc),
+                            str::buf(cx.names.next("str")));
+    llvm::LLVMSetInitializer(g, sc);
+    llvm::LLVMSetGlobalConstant(g, True);
+    llvm::LLVMSetLinkage(g, lib::llvm::LLVMInternalLinkage as llvm::Linkage);
+    ret g;
+}
+
+
+// A rust boxed-and-length-annotated string.
+fn C_str(&@crate_ctxt cx, &str s) -> ValueRef {
+    auto len = str::byte_len(s);
+    auto box =
+        C_struct(~[C_int(abi::const_refcount as int),
+                   C_int(len + 1u as int), // 'alloc'
+                   C_int(len + 1u as int), // 'fill'
+                   C_int(0), // 'pad'
+                   llvm::LLVMConstString(str::buf(s), len, False)]);
+    auto g =
+        llvm::LLVMAddGlobal(cx.llmod, val_ty(box),
+                            str::buf(cx.names.next("str")));
+    llvm::LLVMSetInitializer(g, box);
+    llvm::LLVMSetGlobalConstant(g, True);
+    llvm::LLVMSetLinkage(g, lib::llvm::LLVMInternalLinkage as llvm::Linkage);
+    ret llvm::LLVMConstPointerCast(g, T_ptr(T_str()));
+}
+
+// Returns a Plain Old LLVM String:
+fn C_postr(&str s) -> ValueRef {
+    ret llvm::LLVMConstString(str::buf(s), str::byte_len(s), False);
+}
+
+fn C_zero_byte_arr(uint size) -> ValueRef {
+    auto i = 0u;
+    let ValueRef[] elts = ~[];
+    while (i < size) { elts += ~[C_u8(0u)]; i += 1u; }
+    ret llvm::LLVMConstArray(T_i8(), std::ivec::to_ptr(elts),
+                             std::ivec::len(elts));
+}
+
+fn C_struct(&ValueRef[] elts) -> ValueRef {
+    ret llvm::LLVMConstStruct(std::ivec::to_ptr(elts), std::ivec::len(elts),
+                              False);
+}
+
+fn C_named_struct(TypeRef T, &ValueRef[] elts) -> ValueRef {
+    ret llvm::LLVMConstNamedStruct(T, std::ivec::to_ptr(elts),
+                                   std::ivec::len(elts));
+}
+
+fn C_array(TypeRef ty, &ValueRef[] elts) -> ValueRef {
+    ret llvm::LLVMConstArray(ty, std::ivec::to_ptr(elts),
+                             std::ivec::len(elts));
+}
+
diff --git a/src/comp/rustc.rc b/src/comp/rustc.rc
index 1968cafbe14..817ed6e071b 100644
--- a/src/comp/rustc.rc
+++ b/src/comp/rustc.rc
@@ -15,6 +15,7 @@ use std (name = "std",
          url = "http://rust-lang.org/src/std");
 
 mod middle {
+    mod trans_common;
     mod trans;
     mod trans_alt;
     mod ty;