Move trans::type_of code into its own file
Slowly shrinking base.rs
This commit is contained in:
parent
d85d4f55f7
commit
92a45f5582
|
@ -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);
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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};
|
||||
|
|
|
@ -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"); }
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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() }
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -16,6 +16,7 @@ use std (name = "std",
|
|||
mod middle {
|
||||
mod trans {
|
||||
mod common;
|
||||
mod type_of;
|
||||
mod build;
|
||||
mod base;
|
||||
mod alt;
|
||||
|
|
Loading…
Reference in New Issue