提交 6e909e38 编写于 作者: B Brian Anderson

rustc: Use LLVM named structs for enum types

上级 929c3dd7
......@@ -2243,7 +2243,8 @@ fn trans_var(cx: block, def: ast::def, id: ast::node_id)-> lval_maybe_callee {
// Nullary variant.
let enum_ty = node_id_type(cx, id);
let llenumblob = alloc_ty(cx, enum_ty);
let llenumty = type_of_enum(ccx, tid, enum_ty);
// FIXME: This pointer cast probably isn't necessary
let llenumty = type_of(ccx, enum_ty);
let llenumptr = PointerCast(cx, llenumblob, T_ptr(llenumty));
let lldiscrimptr = GEPi(cx, llenumptr, [0, 0]);
let lldiscrim_gv = lookup_discriminant(ccx, vid);
......
......@@ -7,6 +7,11 @@
import ty::*;
export type_of;
export type_of_explicit_args;
export type_of_fn_from_ty;
export type_of_fn;
fn type_of_explicit_args(cx: @crate_ctxt, inputs: [ty::arg]) -> [TypeRef] {
vec::map(inputs) {|arg|
let arg_ty = arg.ty;
......@@ -39,10 +44,22 @@ fn type_of_fn_from_ty(cx: @crate_ctxt, fty: ty::t) -> TypeRef {
fn type_of(cx: @crate_ctxt, t: ty::t) -> TypeRef {
assert !ty::type_has_vars(t);
// Check the cache.
#debug("type_of %?: %?", t, ty::get(t));
// Check the cache.
if cx.lltypes.contains_key(t) { ret cx.lltypes.get(t); }
let llty = alt ty::get(t).struct {
// Replace any typedef'd types with their equivalent non-typedef
// type. This ensures that all LLVM nominal types that contain
// Rust types are defined as the same LLVM types. If we don't do
// this then, e.g. `option<{myfield: bool}>` would be a different
// type than `option<myrec>`.
let t_norm = ty::normalize_ty(cx.tcx, t);
let llty = if t != t_norm {
type_of(cx, t_norm)
} else {
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) }
......@@ -116,16 +133,60 @@ fn type_of(cx: @crate_ctxt, t: ty::t) -> TypeRef {
ty::ty_self(_) { cx.tcx.sess.unimpl("type_of: ty_self \
not implemented"); }
ty::ty_var(_) { cx.tcx.sess.bug("type_of shouldn't see a ty_var"); }
}
};
cx.lltypes.insert(t, llty);
ret llty;
}
// This should only be called from type_of, above, because it
// creates new llvm named struct types lazily that are then
// cached by type_of
fn type_of_enum(cx: @crate_ctxt, did: ast::def_id, t: ty::t)
-> TypeRef {
#debug("type_of_enum %?: %?", t, ty::get(t));
// Every enum type has a unique name. When we find our roots
// for GC and unwinding we will use this name to rediscover
// the Rust type
let name = llvm_type_name(cx, t);
let named_llty = common::T_named_struct(name);
let lltys = {
let degen = (*ty::enum_variants(cx.tcx, did)).len() == 1u;
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) }
if !degen {
[T_enum_variant(cx), T_array(T_i8(), size)]
}
else if size == 0u {
[T_enum_variant(cx)]
}
else {
[T_array(T_i8(), size)]
}
};
common::set_struct_body(named_llty, lltys);
ret named_llty;
}
fn llvm_type_name(cx: @crate_ctxt, t: ty::t) -> str {
let (name, did, tps) = alt check ty::get(t).struct {
ty::ty_enum(did, substs) {
("enum", did, substs.tps)
}
};
ret #fmt(
"%s %s[#%d]",
name,
util::ppaux::parameterized(
cx.tcx,
ty::item_path_str(cx.tcx, did),
none,
tps),
did.crate
);
}
......@@ -149,6 +149,7 @@
export atttce_unresolved, atttce_resolved;
export mach_sty;
export ty_sort_str;
export normalize_ty;
// Data types
......@@ -2674,6 +2675,27 @@ fn ty_params_to_tys(tcx: ty::ctxt, tps: [ast::ty_param]) -> [t] {
ty::mk_param(tcx, i, ast_util::local_def(tps[i].id))
})
}
#[doc = "
Returns an equivalent type with all the typedefs and self regions removed
"]
fn normalize_ty(cx: ctxt, t: t) -> t {
let t = alt get(t).struct {
ty_enum(did, r) {
alt r.self_r {
some(_) {
// This enum has a self region. Get rid of it
mk_enum(cx, did, {self_r: none, tps: r.tps })
}
none { t }
}
}
_ { t }
};
let sty = fold_sty(get(t).struct) {|t| normalize_ty(cx, t) };
mk_t(cx, sty)
}
// Local Variables:
// mode: rust
// fill-column: 78;
......
......@@ -128,25 +128,6 @@ fn method_to_str(cx: ctxt, m: method) -> str {
fn field_to_str(cx: ctxt, f: field) -> str {
ret f.ident + ": " + mt_to_str(cx, f.mt);
}
fn parameterized(cx: ctxt,
base: str,
self_r: option<ty::region>,
tps: [ty::t]) -> str {
let r_str = alt self_r {
none { "" }
some(r) {
#fmt["/%s", region_to_str(cx, r)]
}
};
if vec::len(tps) > 0u {
let strs = vec::map(tps, {|t| ty_to_str(cx, t)});
#fmt["%s%s<%s>", base, r_str, str::connect(strs, ",")]
} else {
#fmt["%s%s", base, r_str]
}
}
// if there is an id, print that instead of the structural type:
alt ty::type_def_id(typ) {
......@@ -233,6 +214,26 @@ fn parameterized(cx: ctxt,
}
}
fn parameterized(cx: ctxt,
base: str,
self_r: option<ty::region>,
tps: [ty::t]) -> str {
let r_str = alt self_r {
none { "" }
some(r) {
#fmt["/%s", region_to_str(cx, r)]
}
};
if vec::len(tps) > 0u {
let strs = vec::map(tps, {|t| ty_to_str(cx, t)});
#fmt["%s%s<%s>", base, r_str, str::connect(strs, ",")]
} else {
#fmt["%s%s", base, r_str]
}
}
fn ty_to_short_str(cx: ctxt, typ: t) -> str {
let mut s = encoder::encoded_ty(cx, typ);
if str::len(s) >= 32u { s = str::slice(s, 0u, 32u); }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册