Move trans::type_of code into its own file

Slowly shrinking base.rs
This commit is contained in:
Marijn Haverbeke 2012-02-21 15:22:55 +01:00
parent d85d4f55f7
commit 92a45f5582
11 changed files with 227 additions and 224 deletions

View File

@ -686,7 +686,7 @@ fn bind_irrefutable_pat(bcx: block, pat: @ast::pat, val: ValueRef,
ast::pat_ident(_,inner) {
if make_copy || ccx.copy_map.contains_key(pat.id) {
let ty = node_id_type(bcx, pat.id);
let llty = type_of(ccx, ty);
let llty = type_of::type_of(ccx, ty);
let alloc = alloca(bcx, llty);
bcx = copy_val(bcx, INIT, alloc,
load_if_immediate(bcx, val, ty), ty);

View File

@ -44,157 +44,80 @@ import util::ppaux::{ty_to_str, ty_to_short_str};
import common::*;
import build::*;
import shape::*;
import type_of::*;
import type_of::type_of; // Issue #1873
import ast_map::{path, path_mod, path_name};
fn type_of_explicit_args(cx: crate_ctxt, inputs: [ty::arg]) -> [TypeRef] {
vec::map(inputs) {|arg|
let arg_ty = arg.ty;
let llty = type_of(cx, arg_ty);
alt ty::resolved_mode(cx.tcx, arg.mode) {
ast::by_val { llty }
_ { T_ptr(llty) }
}
// Destinations
// These are passed around by the code generating functions to track the
// destination of a computation's value.
enum dest {
by_val(@mutable ValueRef),
save_in(ValueRef),
ignore,
}
fn empty_dest_cell() -> @mutable ValueRef {
ret @mutable llvm::LLVMGetUndef(T_nil());
}
fn dup_for_join(dest: dest) -> dest {
alt dest {
by_val(_) { by_val(empty_dest_cell()) }
_ { dest }
}
}
// NB: must keep 4 fns in sync:
//
// - type_of_fn
// - create_llargs_for_fn_args.
// - new_fn_ctxt
// - trans_args
fn type_of_fn(cx: crate_ctxt, inputs: [ty::arg],
output: ty::t, params: [ty::param_bounds]) -> TypeRef {
let atys: [TypeRef] = [];
// Arg 0: Output pointer.
atys += [T_ptr(type_of(cx, output))];
// Arg 1: Environment
atys += [T_opaque_box_ptr(cx)];
// Args >2: ty params, if not acquired via capture...
for bounds in params {
atys += [T_ptr(cx.tydesc_type)];
for bound in *bounds {
alt bound {
ty::bound_iface(_) { atys += [T_ptr(T_dict())]; }
fn join_returns(parent_cx: block, in_cxs: [block],
in_ds: [dest], out_dest: dest) -> block {
let out = sub_block(parent_cx, "join");
let reachable = false, i = 0u, phi = none;
for cx in in_cxs {
if !cx.unreachable {
Br(cx, out.llbb);
reachable = true;
alt in_ds[i] {
by_val(cell) {
if option::is_none(phi) {
phi = some(EmptyPhi(out, val_ty(*cell)));
}
AddIncomingToPhi(option::get(phi), *cell, cx.llbb);
}
_ {}
}
}
i += 1u;
}
// ... then explicit args.
atys += type_of_explicit_args(cx, inputs);
ret T_fn(atys, llvm::LLVMVoidType());
}
// Given a function type and a count of ty params, construct an llvm type
fn type_of_fn_from_ty(cx: crate_ctxt, fty: ty::t,
param_bounds: [ty::param_bounds]) -> TypeRef {
type_of_fn(cx, ty::ty_fn_args(fty), ty::ty_fn_ret(fty), param_bounds)
}
fn type_of(cx: crate_ctxt, t: ty::t) -> TypeRef {
assert !ty::type_has_vars(t);
// Check the cache.
if cx.lltypes.contains_key(t) { ret cx.lltypes.get(t); }
let llty = alt ty::get(t).struct {
ty::ty_nil | ty::ty_bot { T_nil() }
ty::ty_bool { T_bool() }
ty::ty_int(t) { T_int_ty(cx, t) }
ty::ty_uint(t) { T_uint_ty(cx, t) }
ty::ty_float(t) { T_float_ty(cx, t) }
ty::ty_str { T_ptr(T_vec(cx, T_i8())) }
ty::ty_enum(did, _) { type_of_enum(cx, did, t) }
ty::ty_box(mt) {
let mt_ty = mt.ty;
T_ptr(T_box(cx, type_of(cx, mt_ty))) }
ty::ty_opaque_box { T_ptr(T_box(cx, T_i8())) }
ty::ty_uniq(mt) {
let mt_ty = mt.ty;
T_ptr(type_of(cx, mt_ty)) }
ty::ty_vec(mt) {
let mt_ty = mt.ty;
if ty::type_has_dynamic_size(cx.tcx, mt_ty) {
T_ptr(cx.opaque_vec_type)
} else {
T_ptr(T_vec(cx, type_of(cx, mt_ty))) }
}
ty::ty_ptr(mt) {
let mt_ty = mt.ty;
T_ptr(type_of(cx, mt_ty)) }
ty::ty_rec(fields) {
let tys: [TypeRef] = [];
for f: ty::field in fields {
let mt_ty = f.mt.ty;
tys += [type_of(cx, mt_ty)];
if !reachable {
Unreachable(out);
} else {
alt out_dest {
by_val(cell) { *cell = option::get(phi); }
_ {}
}
T_struct(tys)
}
ty::ty_fn(_) {
T_fn_pair(cx, type_of_fn_from_ty(cx, t, []))
}
ty::ty_iface(_, _) { T_opaque_iface(cx) }
ty::ty_res(_, sub, tps) {
let sub1 = ty::substitute_type_params(cx.tcx, tps, sub);
ret T_struct([T_i8(), type_of(cx, sub1)]);
}
ty::ty_param(_, _) { T_typaram(cx.tn) }
ty::ty_send_type | ty::ty_type { T_ptr(cx.tydesc_type) }
ty::ty_tup(elts) {
let tys = [];
for elt in elts {
tys += [type_of(cx, elt)];
}
T_struct(tys)
}
ty::ty_opaque_closure_ptr(_) { T_opaque_box_ptr(cx) }
ty::ty_constr(subt,_) { type_of(cx, subt) }
_ { fail "type_of not implemented for this kind of type"; }
};
cx.lltypes.insert(t, llty);
ret llty;
}
ret out;
}
fn type_of_enum(cx: crate_ctxt, did: ast::def_id, t: ty::t)
-> TypeRef {
let degen = (*ty::enum_variants(cx.tcx, did)).len() == 1u;
if check type_has_static_size(cx, t) {
let size = static_size_of_enum(cx, t);
if !degen { T_enum(cx, size) }
else if size == 0u { T_struct([T_enum_variant(cx)]) }
else { T_array(T_i8(), size) }
// Used to put an immediate value in a dest.
fn store_in_dest(bcx: block, val: ValueRef, dest: dest) -> block {
alt dest {
ignore {}
by_val(cell) { *cell = val; }
save_in(addr) { Store(bcx, val, addr); }
}
else {
if degen { T_struct([T_enum_variant(cx)]) }
else { T_opaque_enum(cx) }
ret bcx;
}
fn get_dest_addr(dest: dest) -> ValueRef {
alt dest {
save_in(a) { a }
_ { fail "get_dest_addr: not a save_in"; }
}
}
fn type_of_ty_param_bounds_and_ty
(ccx: crate_ctxt, tpt: ty::ty_param_bounds_and_ty) -> TypeRef {
let t = tpt.ty;
alt ty::get(t).struct {
ty::ty_fn(_) {
ret type_of_fn_from_ty(ccx, t, *tpt.bounds);
}
_ {
// fall through
}
}
type_of(ccx, t)
}
fn type_of_or_i8(ccx: crate_ctxt, typ: ty::t) -> TypeRef {
if check type_has_static_size(ccx, typ) {
type_of(ccx, typ)
} else { T_i8() }
}
// Name sanitation. LLVM will happily accept identifiers with weird names, but
// gas doesn't!
fn sanitize(s: str) -> str {
@ -1886,8 +1809,6 @@ fn trans_lazy_binop(bcx: block, op: lazy_binop_ty, a: @ast::expr,
ret store_in_dest(join, phi, dest);
}
fn trans_binary(bcx: block, op: ast::binop, lhs: @ast::expr,
rhs: @ast::expr, dest: dest, ex: @ast::expr) -> block {
// User-defined operators
@ -1921,71 +1842,6 @@ fn trans_binary(bcx: block, op: ast::binop, lhs: @ast::expr,
}
}
enum dest {
by_val(@mutable ValueRef),
save_in(ValueRef),
ignore,
}
fn empty_dest_cell() -> @mutable ValueRef {
ret @mutable llvm::LLVMGetUndef(T_nil());
}
fn dup_for_join(dest: dest) -> dest {
alt dest {
by_val(_) { by_val(empty_dest_cell()) }
_ { dest }
}
}
fn join_returns(parent_cx: block, in_cxs: [block],
in_ds: [dest], out_dest: dest) -> block {
let out = sub_block(parent_cx, "join");
let reachable = false, i = 0u, phi = none;
for cx in in_cxs {
if !cx.unreachable {
Br(cx, out.llbb);
reachable = true;
alt in_ds[i] {
by_val(cell) {
if option::is_none(phi) {
phi = some(EmptyPhi(out, val_ty(*cell)));
}
AddIncomingToPhi(option::get(phi), *cell, cx.llbb);
}
_ {}
}
}
i += 1u;
}
if !reachable {
Unreachable(out);
} else {
alt out_dest {
by_val(cell) { *cell = option::get(phi); }
_ {}
}
}
ret out;
}
// Used to put an immediate value in a dest.
fn store_in_dest(bcx: block, val: ValueRef, dest: dest) -> block {
alt dest {
ignore {}
by_val(cell) { *cell = val; }
save_in(addr) { Store(bcx, val, addr); }
}
ret bcx;
}
fn get_dest_addr(dest: dest) -> ValueRef {
alt dest {
save_in(a) { a }
_ { fail "get_dest_addr: not a save_in"; }
}
}
fn trans_if(cx: block, cond: @ast::expr, thn: ast::blk,
els: option<@ast::expr>, dest: dest)
-> block {

View File

@ -6,6 +6,8 @@ import lib::llvm::{ValueRef, TypeRef};
import common::*;
import build::*;
import base::*;
import type_of::*;
import type_of::type_of; // Issue #1873
import middle::freevars::{get_freevars, freevar_info};
import back::abi;
import syntax::codemap::span;

View File

@ -20,9 +20,6 @@ import lib::llvm::{True, False, Bool};
import metadata::csearch;
import ast_map::path;
// FIXME: These should probably be pulled in here too.
import base::{type_of_fn, drop_ty};
type namegen = fn@(str) -> str;
fn new_namegen() -> namegen {
let i = @mutable 0;
@ -231,7 +228,7 @@ fn scope_clean_changed(info: scope_info) {
fn add_clean(cx: block, val: ValueRef, ty: ty::t) {
if !ty::type_needs_drop(cx.tcx(), ty) { ret; }
in_scope_cx(cx) {|info|
info.cleanups += [clean(bind drop_ty(_, val, ty))];
info.cleanups += [clean(bind base::drop_ty(_, val, ty))];
scope_clean_changed(info);
}
}
@ -242,7 +239,7 @@ fn add_clean_temp(cx: block, val: ValueRef, ty: ty::t) {
if ty::type_is_immediate(ty) {
ret base::drop_ty_immediate(bcx, val, ty);
} else {
ret drop_ty(bcx, val, ty);
ret base::drop_ty(bcx, val, ty);
}
}
in_scope_cx(cx) {|info|
@ -253,7 +250,7 @@ fn add_clean_temp(cx: block, val: ValueRef, ty: ty::t) {
fn add_clean_temp_mem(cx: block, val: ValueRef, ty: ty::t) {
if !ty::type_needs_drop(cx.tcx(), ty) { ret; }
in_scope_cx(cx) {|info|
info.cleanups += [clean_temp(val, bind drop_ty(_, val, ty))];
info.cleanups += [clean_temp(val, bind base::drop_ty(_, val, ty))];
scope_clean_changed(info);
}
}
@ -301,8 +298,8 @@ fn get_res_dtor(ccx: crate_ctxt, did: ast::def_id, inner_t: ty::t)
let param_bounds = ty::lookup_item_type(ccx.tcx, did).bounds;
let nil_res = ty::mk_nil(ccx.tcx);
let fn_mode = ast::expl(ast::by_ref);
let f_t = type_of_fn(ccx, [{mode: fn_mode, ty: inner_t}],
nil_res, *param_bounds);
let f_t = type_of::type_of_fn(ccx, [{mode: fn_mode, ty: inner_t}],
nil_res, *param_bounds);
ret base::get_extern_const(ccx.externs, ccx.llmod,
csearch::get_symbol(ccx.sess.cstore,
did), f_t);

View File

@ -1,6 +1,7 @@
import ctypes::c_uint;
import base::*;
import common::*;
import type_of::*;
import build::*;
import driver::session::session;
import syntax::{ast, ast_util};

View File

@ -8,6 +8,7 @@ import back::link;
import common::*;
import build::*;
import base::*;
import type_of::*;
export link_name, trans_native_mod, register_crust_fn, trans_crust_fn;
@ -31,7 +32,7 @@ fn c_arg_and_ret_lltys(ccx: crate_ctxt,
alt ty::get(ty::node_id_to_type(ccx.tcx, id)).struct {
ty::ty_fn({inputs: arg_tys, output: ret_ty, _}) {
let llargtys = type_of_explicit_args(ccx, arg_tys);
let llretty = type_of(ccx, ret_ty);
let llretty = type_of::type_of(ccx, ret_ty);
(llargtys, llretty, ret_ty)
}
_ { ccx.sess.bug("c_arg_and_ret_lltys called on non-function type"); }

View File

@ -118,7 +118,7 @@ fn largest_variants(ccx: crate_ctxt, tag_id: ast::def_id) -> [uint] {
// when in fact it has minimum size sizeof(int).
bounded = false;
} else {
let llty = base::type_of(ccx, elem_t);
let llty = type_of::type_of(ccx, elem_t);
min_size += llsize_of_real(ccx, llty);
min_align += llalign_of_real(ccx, llty);
}
@ -188,7 +188,7 @@ fn compute_static_enum_size(ccx: crate_ctxt, largest_variants: [uint],
// We increment a "virtual data pointer" to compute the size.
let lltys = [];
for typ: ty::t in variants[vid].args {
lltys += [base::type_of(ccx, typ)];
lltys += [type_of::type_of(ccx, typ)];
}
let llty = trans::common::T_struct(lltys);
@ -590,7 +590,7 @@ type tag_metrics = {
fn size_of(bcx: block, t: ty::t) -> result {
let ccx = bcx.ccx();
if check type_has_static_size(ccx, t) {
rslt(bcx, llsize_of(ccx, base::type_of(ccx, t)))
rslt(bcx, llsize_of(ccx, type_of::type_of(ccx, t)))
} else {
let { bcx, sz, align: _ } = dynamic_metrics(bcx, t);
rslt(bcx, sz)
@ -600,7 +600,7 @@ fn size_of(bcx: block, t: ty::t) -> result {
fn align_of(bcx: block, t: ty::t) -> result {
let ccx = bcx.ccx();
if check type_has_static_size(ccx, t) {
rslt(bcx, llalign_of(ccx, base::type_of(ccx, t)))
rslt(bcx, llalign_of(ccx, type_of::type_of(ccx, t)))
} else {
let { bcx, sz: _, align } = dynamic_metrics(bcx, t);
rslt(bcx, align)
@ -610,7 +610,7 @@ fn align_of(bcx: block, t: ty::t) -> result {
fn metrics(bcx: block, t: ty::t) -> metrics {
let ccx = bcx.ccx();
if check type_has_static_size(ccx, t) {
let llty = base::type_of(ccx, t);
let llty = type_of::type_of(ccx, t);
{ bcx: bcx, sz: llsize_of(ccx, llty), align: llalign_of(ccx, llty) }
} else {
dynamic_metrics(bcx, t)
@ -657,7 +657,7 @@ fn static_size_of_enum(cx: crate_ctxt, t: ty::t) -> uint {
tup_ty = ty::substitute_type_params(cx.tcx, subtys, tup_ty);
// Here we possibly do a recursive call.
let this_size =
llsize_of_real(cx, base::type_of(cx, tup_ty));
llsize_of_real(cx, type_of::type_of(cx, tup_ty));
if max_size < this_size { max_size = this_size; }
}
cx.enum_sizes.insert(t, max_size);

View File

@ -2,7 +2,7 @@ import syntax::ast;
import driver::session::session;
import lib::llvm::{ValueRef, TypeRef};
import back::abi;
import base::{call_memmove, trans_shared_malloc, type_of_or_i8,
import base::{call_memmove, trans_shared_malloc,
INIT, copy_val, load_if_immediate, get_tydesc,
sub_block, do_spill_noroot,
dest};
@ -46,7 +46,7 @@ type alloc_result =
fn alloc(bcx: block, vec_ty: ty::t, elts: uint) -> alloc_result {
let ccx = bcx.ccx();
let unit_ty = ty::sequence_element_type(bcx.tcx(), vec_ty);
let llunitty = type_of_or_i8(ccx, unit_ty);
let llunitty = type_of::type_of_or_i8(ccx, unit_ty);
let llvecty = T_vec(ccx, llunitty);
let {bcx: bcx, val: unit_sz} = size_of(bcx, unit_ty);
@ -156,7 +156,7 @@ fn trans_append(cx: block, vec_ty: ty::t, lhsptr: ValueRef,
};
let {bcx: bcx, val: unit_sz} = size_of(cx, unit_ty);
let llunitty = type_of_or_i8(ccx, unit_ty);
let llunitty = type_of::type_of_or_i8(ccx, unit_ty);
let lhs = Load(bcx, lhsptr);
let self_append = ICmp(bcx, lib::llvm::IntEQ, lhs, rhs);
@ -226,7 +226,7 @@ fn trans_add(bcx: block, vec_ty: ty::t, lhs: ValueRef,
_ { false }
};
let unit_ty = ty::sequence_element_type(bcx.tcx(), vec_ty);
let llunitty = type_of_or_i8(ccx, unit_ty);
let llunitty = type_of::type_of_or_i8(ccx, unit_ty);
let {bcx: bcx, val: llunitsz} = size_of(bcx, unit_ty);
let lhs_fill = get_fill(bcx, lhs);
@ -268,7 +268,7 @@ fn iter_vec_raw(bcx: block, vptr: ValueRef, vec_ty: ty::t,
fill: ValueRef, f: iter_vec_block) -> block {
let ccx = bcx.ccx();
let unit_ty = ty::sequence_element_type(bcx.tcx(), vec_ty);
let llunitty = type_of_or_i8(ccx, unit_ty);
let llunitty = type_of::type_of_or_i8(ccx, unit_ty);
let {bcx: bcx, val: unit_sz} = size_of(bcx, unit_ty);
let vptr = PointerCast(bcx, vptr, T_ptr(T_vec(ccx, llunitty)));
let data_ptr = get_dataptr(bcx, vptr, llunitty);

View File

@ -0,0 +1,145 @@
import common::*;
import lib::llvm::{TypeRef};
import syntax::ast;
import lib::llvm::llvm;
fn type_of_explicit_args(cx: crate_ctxt, inputs: [ty::arg]) -> [TypeRef] {
vec::map(inputs) {|arg|
let arg_ty = arg.ty;
let llty = type_of(cx, arg_ty);
alt ty::resolved_mode(cx.tcx, arg.mode) {
ast::by_val { llty }
_ { T_ptr(llty) }
}
}
}
fn type_of_fn(cx: crate_ctxt, inputs: [ty::arg],
output: ty::t, params: [ty::param_bounds]) -> TypeRef {
let atys: [TypeRef] = [];
// Arg 0: Output pointer.
atys += [T_ptr(type_of(cx, output))];
// Arg 1: Environment
atys += [T_opaque_box_ptr(cx)];
// Args >2: ty params, if not acquired via capture...
for bounds in params {
atys += [T_ptr(cx.tydesc_type)];
for bound in *bounds {
alt bound {
ty::bound_iface(_) { atys += [T_ptr(T_dict())]; }
_ {}
}
}
}
// ... then explicit args.
atys += type_of_explicit_args(cx, inputs);
ret T_fn(atys, llvm::LLVMVoidType());
}
// Given a function type and a count of ty params, construct an llvm type
fn type_of_fn_from_ty(cx: crate_ctxt, fty: ty::t,
param_bounds: [ty::param_bounds]) -> TypeRef {
type_of_fn(cx, ty::ty_fn_args(fty), ty::ty_fn_ret(fty), param_bounds)
}
fn type_of(cx: crate_ctxt, t: ty::t) -> TypeRef {
assert !ty::type_has_vars(t);
// Check the cache.
if cx.lltypes.contains_key(t) { ret cx.lltypes.get(t); }
let llty = alt ty::get(t).struct {
ty::ty_nil | ty::ty_bot { T_nil() }
ty::ty_bool { T_bool() }
ty::ty_int(t) { T_int_ty(cx, t) }
ty::ty_uint(t) { T_uint_ty(cx, t) }
ty::ty_float(t) { T_float_ty(cx, t) }
ty::ty_str { T_ptr(T_vec(cx, T_i8())) }
ty::ty_enum(did, _) { type_of_enum(cx, did, t) }
ty::ty_box(mt) {
let mt_ty = mt.ty;
T_ptr(T_box(cx, type_of(cx, mt_ty))) }
ty::ty_opaque_box { T_ptr(T_box(cx, T_i8())) }
ty::ty_uniq(mt) {
let mt_ty = mt.ty;
T_ptr(type_of(cx, mt_ty)) }
ty::ty_vec(mt) {
let mt_ty = mt.ty;
if ty::type_has_dynamic_size(cx.tcx, mt_ty) {
T_ptr(cx.opaque_vec_type)
} else {
T_ptr(T_vec(cx, type_of(cx, mt_ty))) }
}
ty::ty_ptr(mt) {
let mt_ty = mt.ty;
T_ptr(type_of(cx, mt_ty)) }
ty::ty_rec(fields) {
let tys: [TypeRef] = [];
for f: ty::field in fields {
let mt_ty = f.mt.ty;
tys += [type_of(cx, mt_ty)];
}
T_struct(tys)
}
ty::ty_fn(_) {
T_fn_pair(cx, type_of_fn_from_ty(cx, t, []))
}
ty::ty_iface(_, _) { T_opaque_iface(cx) }
ty::ty_res(_, sub, tps) {
let sub1 = ty::substitute_type_params(cx.tcx, tps, sub);
ret T_struct([T_i8(), type_of(cx, sub1)]);
}
ty::ty_param(_, _) { T_typaram(cx.tn) }
ty::ty_send_type | ty::ty_type { T_ptr(cx.tydesc_type) }
ty::ty_tup(elts) {
let tys = [];
for elt in elts {
tys += [type_of(cx, elt)];
}
T_struct(tys)
}
ty::ty_opaque_closure_ptr(_) { T_opaque_box_ptr(cx) }
ty::ty_constr(subt,_) { type_of(cx, subt) }
_ { fail "type_of not implemented for this kind of type"; }
};
cx.lltypes.insert(t, llty);
ret llty;
}
fn type_of_enum(cx: crate_ctxt, did: ast::def_id, t: ty::t)
-> TypeRef {
let degen = (*ty::enum_variants(cx.tcx, did)).len() == 1u;
if check type_has_static_size(cx, t) {
let size = shape::static_size_of_enum(cx, t);
if !degen { T_enum(cx, size) }
else if size == 0u { T_struct([T_enum_variant(cx)]) }
else { T_array(T_i8(), size) }
}
else {
if degen { T_struct([T_enum_variant(cx)]) }
else { T_opaque_enum(cx) }
}
}
fn type_of_ty_param_bounds_and_ty
(ccx: crate_ctxt, tpt: ty::ty_param_bounds_and_ty) -> TypeRef {
let t = tpt.ty;
alt ty::get(t).struct {
ty::ty_fn(_) {
ret type_of_fn_from_ty(ccx, t, *tpt.bounds);
}
_ {
// fall through
}
}
type_of(ccx, t)
}
fn type_of_or_i8(ccx: crate_ctxt, typ: ty::t) -> TypeRef {
if check type_has_static_size(ccx, typ) {
type_of(ccx, typ)
} else { T_i8() }
}

View File

@ -24,7 +24,7 @@ fn alloc_uniq(cx: block, uniq_ty: ty::t) -> result {
bcx = r.bcx;
let llsz = r.val;
let llptrty = T_ptr(type_of(bcx.ccx(), contents_ty));
let llptrty = T_ptr(type_of::type_of(bcx.ccx(), contents_ty));
r = trans_shared_malloc(bcx, llptrty, llsz);
bcx = r.bcx;

View File

@ -16,6 +16,7 @@ use std (name = "std",
mod middle {
mod trans {
mod common;
mod type_of;
mod build;
mod base;
mod alt;