Skip to content

Commit a770d86

Browse files
committed
rustc: Move generally useful functions out of shape.rs in preparation for its destruction
1 parent 349ef79 commit a770d86

File tree

3 files changed

+150
-143
lines changed

3 files changed

+150
-143
lines changed

src/rustc/middle/trans/machine.rs

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
// Information concerning the machine representation of various types.
2+
3+
use middle::trans::common::*;
4+
5+
// Creates a simpler, size-equivalent type. The resulting type is guaranteed
6+
// to have (a) the same size as the type that was passed in; (b) to be non-
7+
// recursive. This is done by replacing all boxes in a type with boxed unit
8+
// types.
9+
// This should reduce all pointers to some simple pointer type, to
10+
// ensure that we don't recurse endlessly when computing the size of a
11+
// nominal type that has pointers to itself in it.
12+
pub fn simplify_type(tcx: ty::ctxt, typ: ty::t) -> ty::t {
13+
fn nilptr(tcx: ty::ctxt) -> ty::t {
14+
ty::mk_ptr(tcx, {ty: ty::mk_nil(tcx), mutbl: ast::m_imm})
15+
}
16+
fn simplifier(tcx: ty::ctxt, typ: ty::t) -> ty::t {
17+
match ty::get(typ).sty {
18+
ty::ty_box(_) | ty::ty_opaque_box | ty::ty_uniq(_) |
19+
ty::ty_evec(_, ty::vstore_uniq) | ty::ty_evec(_, ty::vstore_box) |
20+
ty::ty_estr(ty::vstore_uniq) | ty::ty_estr(ty::vstore_box) |
21+
ty::ty_ptr(_) | ty::ty_rptr(_,_) => nilptr(tcx),
22+
ty::ty_fn(_) => ty::mk_tup(tcx, ~[nilptr(tcx), nilptr(tcx)]),
23+
ty::ty_evec(_, ty::vstore_slice(_)) |
24+
ty::ty_estr(ty::vstore_slice(_)) => {
25+
ty::mk_tup(tcx, ~[nilptr(tcx), ty::mk_int(tcx)])
26+
}
27+
// Reduce a class type to a record type in which all the fields are
28+
// simplified
29+
ty::ty_class(did, ref substs) => {
30+
let simpl_fields = (if ty::ty_dtor(tcx, did).is_some() {
31+
// remember the drop flag
32+
~[{ident: syntax::parse::token::special_idents::dtor,
33+
mt: {ty: ty::mk_u8(tcx),
34+
mutbl: ast::m_mutbl}}] }
35+
else { ~[] }) +
36+
do ty::lookup_class_fields(tcx, did).map |f| {
37+
let t = ty::lookup_field_type(tcx, did, f.id, substs);
38+
{ident: f.ident,
39+
mt: {ty: simplify_type(tcx, t), mutbl: ast::m_const}}
40+
};
41+
ty::mk_rec(tcx, simpl_fields)
42+
}
43+
_ => typ
44+
}
45+
}
46+
ty::fold_ty(tcx, typ, |t| simplifier(tcx, t))
47+
}
48+
49+
// ______________________________________________________________________
50+
// compute sizeof / alignof
51+
52+
pub type metrics = {
53+
bcx: block,
54+
sz: ValueRef,
55+
align: ValueRef
56+
};
57+
58+
pub type tag_metrics = {
59+
bcx: block,
60+
sz: ValueRef,
61+
align: ValueRef,
62+
payload_align: ValueRef
63+
};
64+
65+
// Returns the number of bytes clobbered by a Store to this type.
66+
pub fn llsize_of_store(cx: @crate_ctxt, t: TypeRef) -> uint {
67+
return llvm::LLVMStoreSizeOfType(cx.td.lltd, t) as uint;
68+
}
69+
70+
// Returns the number of bytes between successive elements of type T in an
71+
// array of T. This is the "ABI" size. It includes any ABI-mandated padding.
72+
pub fn llsize_of_alloc(cx: @crate_ctxt, t: TypeRef) -> uint {
73+
return llvm::LLVMABISizeOfType(cx.td.lltd, t) as uint;
74+
}
75+
76+
// Returns, as near as we can figure, the "real" size of a type. As in, the
77+
// bits in this number of bytes actually carry data related to the datum
78+
// with the type. Not junk, padding, accidentally-damaged words, or
79+
// whatever. Rounds up to the nearest byte though, so if you have a 1-bit
80+
// value, we return 1 here, not 0. Most of rustc works in bytes.
81+
pub fn llsize_of_real(cx: @crate_ctxt, t: TypeRef) -> uint {
82+
let nbits = llvm::LLVMSizeOfTypeInBits(cx.td.lltd, t) as uint;
83+
if nbits & 7u != 0u {
84+
// Not an even number of bytes, spills into "next" byte.
85+
1u + (nbits >> 3)
86+
} else {
87+
nbits >> 3
88+
}
89+
}
90+
91+
// Returns the "default" size of t, which is calculated by casting null to a
92+
// *T and then doing gep(1) on it and measuring the result. Really, look in
93+
// the LLVM sources. It does that. So this is likely similar to the ABI size
94+
// (i.e. including alignment-padding), but goodness knows which alignment it
95+
// winds up using. Probably the ABI one? Not recommended.
96+
pub fn llsize_of(cx: @crate_ctxt, t: TypeRef) -> ValueRef {
97+
return llvm::LLVMConstIntCast(lib::llvm::llvm::LLVMSizeOf(t), cx.int_type,
98+
False);
99+
}
100+
101+
// Returns the preferred alignment of the given type for the current target.
102+
// The preffered alignment may be larger than the alignment used when
103+
// packing the type into structs. This will be used for things like
104+
// allocations inside a stack frame, which LLVM has a free hand in.
105+
pub fn llalign_of_pref(cx: @crate_ctxt, t: TypeRef) -> uint {
106+
return llvm::LLVMPreferredAlignmentOfType(cx.td.lltd, t) as uint;
107+
}
108+
109+
// Returns the minimum alignment of a type required by the plattform.
110+
// This is the alignment that will be used for struct fields, arrays,
111+
// and similar ABI-mandated things.
112+
pub fn llalign_of_min(cx: @crate_ctxt, t: TypeRef) -> uint {
113+
return llvm::LLVMABIAlignmentOfType(cx.td.lltd, t) as uint;
114+
}
115+
116+
// Returns the "default" alignment of t, which is calculated by casting
117+
// null to a record containing a single-bit followed by a t value, then
118+
// doing gep(0,1) to get at the trailing (and presumably padded) t cell.
119+
pub fn llalign_of(cx: @crate_ctxt, t: TypeRef) -> ValueRef {
120+
return llvm::LLVMConstIntCast(
121+
lib::llvm::llvm::LLVMAlignOf(t), cx.int_type, False);
122+
}
123+
124+
// Computes the size of the data part of an enum.
125+
pub fn static_size_of_enum(cx: @crate_ctxt, t: ty::t) -> uint {
126+
if cx.enum_sizes.contains_key(t) { return cx.enum_sizes.get(t); }
127+
match ty::get(t).sty {
128+
ty::ty_enum(tid, ref substs) => {
129+
// Compute max(variant sizes).
130+
let mut max_size = 0u;
131+
let variants = ty::enum_variants(cx.tcx, tid);
132+
for vec::each(*variants) |variant| {
133+
let tup_ty = simplify_type(cx.tcx,
134+
ty::mk_tup(cx.tcx, variant.args));
135+
// Perform any type parameter substitutions.
136+
let tup_ty = ty::subst(cx.tcx, substs, tup_ty);
137+
// Here we possibly do a recursive call.
138+
let this_size =
139+
llsize_of_real(cx, type_of::type_of(cx, tup_ty));
140+
if max_size < this_size { max_size = this_size; }
141+
}
142+
cx.enum_sizes.insert(t, max_size);
143+
return max_size;
144+
}
145+
_ => cx.sess.bug(~"static_size_of_enum called on non-enum")
146+
}
147+
}
148+

src/rustc/middle/trans/shape.rs

Lines changed: 1 addition & 143 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use driver::session;
77
use driver::session::session;
88
use trans::base;
99
use middle::trans::common::*;
10+
use middle::trans::machine::*;
1011
use back::abi;
1112
use middle::ty;
1213
use middle::ty::field;
@@ -634,151 +635,8 @@ fn gen_shape_tables(ccx: @crate_ctxt) {
634635
lib::llvm::InternalLinkage);
635636
}
636637

637-
// ______________________________________________________________________
638-
// compute sizeof / alignof
639-
640-
type metrics = {
641-
bcx: block,
642-
sz: ValueRef,
643-
align: ValueRef
644-
};
645-
646-
type tag_metrics = {
647-
bcx: block,
648-
sz: ValueRef,
649-
align: ValueRef,
650-
payload_align: ValueRef
651-
};
652-
653-
// Returns the number of bytes clobbered by a Store to this type.
654-
fn llsize_of_store(cx: @crate_ctxt, t: TypeRef) -> uint {
655-
return llvm::LLVMStoreSizeOfType(cx.td.lltd, t) as uint;
656-
}
657-
658-
// Returns the number of bytes between successive elements of type T in an
659-
// array of T. This is the "ABI" size. It includes any ABI-mandated padding.
660-
fn llsize_of_alloc(cx: @crate_ctxt, t: TypeRef) -> uint {
661-
return llvm::LLVMABISizeOfType(cx.td.lltd, t) as uint;
662-
}
663-
664-
// Returns, as near as we can figure, the "real" size of a type. As in, the
665-
// bits in this number of bytes actually carry data related to the datum
666-
// with the type. Not junk, padding, accidentally-damaged words, or
667-
// whatever. Rounds up to the nearest byte though, so if you have a 1-bit
668-
// value, we return 1 here, not 0. Most of rustc works in bytes.
669-
fn llsize_of_real(cx: @crate_ctxt, t: TypeRef) -> uint {
670-
let nbits = llvm::LLVMSizeOfTypeInBits(cx.td.lltd, t) as uint;
671-
if nbits & 7u != 0u {
672-
// Not an even number of bytes, spills into "next" byte.
673-
1u + (nbits >> 3)
674-
} else {
675-
nbits >> 3
676-
}
677-
}
678-
679-
// Returns the "default" size of t, which is calculated by casting null to a
680-
// *T and then doing gep(1) on it and measuring the result. Really, look in
681-
// the LLVM sources. It does that. So this is likely similar to the ABI size
682-
// (i.e. including alignment-padding), but goodness knows which alignment it
683-
// winds up using. Probably the ABI one? Not recommended.
684-
fn llsize_of(cx: @crate_ctxt, t: TypeRef) -> ValueRef {
685-
return llvm::LLVMConstIntCast(lib::llvm::llvm::LLVMSizeOf(t), cx.int_type,
686-
False);
687-
}
688-
689-
// Returns the preferred alignment of the given type for the current target.
690-
// The preffered alignment may be larger than the alignment used when
691-
// packing the type into structs. This will be used for things like
692-
// allocations inside a stack frame, which LLVM has a free hand in.
693-
fn llalign_of_pref(cx: @crate_ctxt, t: TypeRef) -> uint {
694-
return llvm::LLVMPreferredAlignmentOfType(cx.td.lltd, t) as uint;
695-
}
696-
697-
// Returns the minimum alignment of a type required by the plattform.
698-
// This is the alignment that will be used for struct fields, arrays,
699-
// and similar ABI-mandated things.
700-
fn llalign_of_min(cx: @crate_ctxt, t: TypeRef) -> uint {
701-
return llvm::LLVMABIAlignmentOfType(cx.td.lltd, t) as uint;
702-
}
703-
704-
// Returns the "default" alignment of t, which is calculated by casting
705-
// null to a record containing a single-bit followed by a t value, then
706-
// doing gep(0,1) to get at the trailing (and presumably padded) t cell.
707-
fn llalign_of(cx: @crate_ctxt, t: TypeRef) -> ValueRef {
708-
return llvm::LLVMConstIntCast(
709-
lib::llvm::llvm::LLVMAlignOf(t), cx.int_type, False);
710-
}
711-
712638
// Computes the static size of a enum, without using mk_tup(), which is
713639
// bad for performance.
714640
//
715641
// NB: Migrate trans over to use this.
716642

717-
// Computes the size of the data part of an enum.
718-
fn static_size_of_enum(cx: @crate_ctxt, t: ty::t) -> uint {
719-
if cx.enum_sizes.contains_key(t) { return cx.enum_sizes.get(t); }
720-
match ty::get(t).sty {
721-
ty::ty_enum(tid, ref substs) => {
722-
// Compute max(variant sizes).
723-
let mut max_size = 0u;
724-
let variants = ty::enum_variants(cx.tcx, tid);
725-
for vec::each(*variants) |variant| {
726-
let tup_ty = simplify_type(cx.tcx,
727-
ty::mk_tup(cx.tcx, variant.args));
728-
// Perform any type parameter substitutions.
729-
let tup_ty = ty::subst(cx.tcx, substs, tup_ty);
730-
// Here we possibly do a recursive call.
731-
let this_size =
732-
llsize_of_real(cx, type_of::type_of(cx, tup_ty));
733-
if max_size < this_size { max_size = this_size; }
734-
}
735-
cx.enum_sizes.insert(t, max_size);
736-
return max_size;
737-
}
738-
_ => cx.sess.bug(~"static_size_of_enum called on non-enum")
739-
}
740-
}
741-
742-
// Creates a simpler, size-equivalent type. The resulting type is guaranteed
743-
// to have (a) the same size as the type that was passed in; (b) to be non-
744-
// recursive. This is done by replacing all boxes in a type with boxed unit
745-
// types.
746-
// This should reduce all pointers to some simple pointer type, to
747-
// ensure that we don't recurse endlessly when computing the size of a
748-
// nominal type that has pointers to itself in it.
749-
fn simplify_type(tcx: ty::ctxt, typ: ty::t) -> ty::t {
750-
fn nilptr(tcx: ty::ctxt) -> ty::t {
751-
ty::mk_ptr(tcx, {ty: ty::mk_nil(tcx), mutbl: ast::m_imm})
752-
}
753-
fn simplifier(tcx: ty::ctxt, typ: ty::t) -> ty::t {
754-
match ty::get(typ).sty {
755-
ty::ty_box(_) | ty::ty_opaque_box | ty::ty_uniq(_) |
756-
ty::ty_evec(_, ty::vstore_uniq) | ty::ty_evec(_, ty::vstore_box) |
757-
ty::ty_estr(ty::vstore_uniq) | ty::ty_estr(ty::vstore_box) |
758-
ty::ty_ptr(_) | ty::ty_rptr(_,_) => nilptr(tcx),
759-
ty::ty_fn(_) => ty::mk_tup(tcx, ~[nilptr(tcx), nilptr(tcx)]),
760-
ty::ty_evec(_, ty::vstore_slice(_)) |
761-
ty::ty_estr(ty::vstore_slice(_)) => {
762-
ty::mk_tup(tcx, ~[nilptr(tcx), ty::mk_int(tcx)])
763-
}
764-
// Reduce a class type to a record type in which all the fields are
765-
// simplified
766-
ty::ty_class(did, ref substs) => {
767-
let simpl_fields = (if ty::ty_dtor(tcx, did).is_some() {
768-
// remember the drop flag
769-
~[{ident: syntax::parse::token::special_idents::dtor,
770-
mt: {ty: ty::mk_u8(tcx),
771-
mutbl: ast::m_mutbl}}] }
772-
else { ~[] }) +
773-
do ty::lookup_class_fields(tcx, did).map |f| {
774-
let t = ty::lookup_field_type(tcx, did, f.id, substs);
775-
{ident: f.ident,
776-
mt: {ty: simplify_type(tcx, t), mutbl: ast::m_const}}
777-
};
778-
ty::mk_rec(tcx, simpl_fields)
779-
}
780-
_ => typ
781-
}
782-
}
783-
ty::fold_ty(tcx, typ, |t| simplifier(tcx, t))
784-
}

src/rustc/rustc.rc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ mod middle {
8686
mod type_use;
8787
#[legacy_exports]
8888
mod reachable;
89+
mod machine;
8990
}
9091
#[legacy_exports]
9192
mod ty;

0 commit comments

Comments
 (0)