Skip to content

Commit 8222f9f

Browse files
committed
---
yaml --- r: 45007 b: refs/heads/master c: 626ad48 h: refs/heads/master i: 45005: f62eab8 45003: a248559 44999: e879a78 44991: d157fdc v: v3
1 parent 3c790be commit 8222f9f

File tree

7 files changed

+376
-30
lines changed

7 files changed

+376
-30
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
refs/heads/master: c3c018f8ab017f915d629b2dfe5f4199d2d0145c
2+
refs/heads/master: 626ad484fecc5703f46812c7916fce6fec03ace9
33
refs/heads/snap-stage1: e33de59e47c5076a89eadeb38f4934f58a3618a6
44
refs/heads/snap-stage3: a6d9689399d091c3265f00434a69c551a61c28dc
55
refs/heads/try: ef355f6332f83371e4acf04fc4eb940ab41d78d3

trunk/src/libcore/bool.rs

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@
1212
//! Boolean logic
1313
1414
use option::{None, Option, Some};
15-
use from_str::FromStr;
16-
1715
#[cfg(notest)] use cmp;
1816

1917
/// Negation / inverse
@@ -48,15 +46,13 @@ pub pure fn is_true(v: bool) -> bool { v }
4846
pub pure fn is_false(v: bool) -> bool { !v }
4947

5048
/// Parse logic value from `s`
51-
impl FromStr for bool {
52-
static pure fn from_str(s: &str) -> Option<bool> {
53-
if s == "true" {
54-
Some(true)
55-
} else if s == "false" {
56-
Some(false)
57-
} else {
58-
None
59-
}
49+
pub pure fn from_str(s: &str) -> Option<bool> {
50+
if s == "true" {
51+
Some(true)
52+
} else if s == "false" {
53+
Some(false)
54+
} else {
55+
None
6056
}
6157
}
6258

@@ -83,10 +79,8 @@ impl cmp::Eq for bool {
8379

8480
#[test]
8581
pub fn test_bool_from_str() {
86-
use from_str::FromStr;
87-
8882
do all_values |v| {
89-
assert Some(v) == FromStr::from_str(to_str(v))
83+
assert Some(v) == from_str(to_str(v))
9084
}
9185
}
9286

trunk/src/libcore/from_str.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,4 @@ use option::Option;
1515
pub trait FromStr {
1616
static pure fn from_str(s: &str) -> Option<Self>;
1717
}
18+
Lines changed: 326 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,326 @@
1+
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
use core::option::{Option, Some, None};
12+
use core::vec;
13+
use lib::llvm::{ValueRef, TypeRef};
14+
use middle::trans::_match;
15+
use middle::trans::build::*;
16+
use middle::trans::common::*;
17+
use middle::trans::machine;
18+
use middle::trans::type_of;
19+
use middle::ty;
20+
use syntax::ast;
21+
use util::ppaux::ty_to_str;
22+
23+
24+
// XXX: should this be done with boxed traits instead of ML-style?
25+
pub enum Repr {
26+
CEnum,
27+
Univariant(Struct, Destructor),
28+
General(~[Struct])
29+
}
30+
31+
enum Destructor {
32+
DtorPresent,
33+
DtorAbsent,
34+
NoDtor
35+
}
36+
37+
struct Struct {
38+
size: u64,
39+
align: u64,
40+
fields: ~[ty::t]
41+
}
42+
43+
44+
pub fn represent_node(bcx: block, node: ast::node_id)
45+
-> Repr {
46+
represent_type(bcx.ccx(), node_id_type(bcx, node))
47+
}
48+
49+
pub fn represent_type(cx: @CrateContext, t: ty::t) -> Repr {
50+
debug!("Representing: %s", ty_to_str(cx.tcx, t));
51+
// XXX: cache this
52+
match ty::get(t).sty {
53+
ty::ty_tup(ref elems) => {
54+
Univariant(mk_struct(cx, *elems), NoDtor)
55+
}
56+
ty::ty_rec(ref fields) => {
57+
// XXX: Are these in the right order?
58+
Univariant(mk_struct(cx, fields.map(|f| f.mt.ty)), DtorAbsent)
59+
}
60+
ty::ty_struct(def_id, ref substs) => {
61+
let fields = ty::lookup_struct_fields(cx.tcx, def_id);
62+
let dt = ty::ty_dtor(cx.tcx, def_id).is_present();
63+
Univariant(mk_struct(cx, fields.map(|field| {
64+
ty::lookup_field_type(cx.tcx, def_id, field.id, substs)
65+
})), if dt { DtorPresent } else { DtorAbsent })
66+
}
67+
ty::ty_enum(def_id, ref substs) => {
68+
struct Case { discr: i64, tys: ~[ty::t] };
69+
70+
let cases = do ty::enum_variants(cx.tcx, def_id).map |vi| {
71+
let arg_tys = do vi.args.map |&raw_ty| {
72+
ty::subst(cx.tcx, substs, raw_ty)
73+
};
74+
Case { discr: vi.disr_val /*bad*/as i64, tys: arg_tys }
75+
};
76+
if cases.len() == 0 {
77+
// Uninhabitable; represent as unit
78+
Univariant(mk_struct(cx, ~[]), NoDtor)
79+
} else if cases.len() == 1 && cases[0].discr == 0 {
80+
// struct, tuple, newtype, etc.
81+
Univariant(mk_struct(cx, cases[0].tys), NoDtor)
82+
} else if cases.all(|c| c.tys.len() == 0) {
83+
CEnum
84+
} else {
85+
if !cases.alli(|i,c| c.discr == (i as i64)) {
86+
cx.sess.bug(fmt!("non-C-like enum %s with specified \
87+
discriminants",
88+
ty::item_path_str(cx.tcx, def_id)))
89+
}
90+
General(cases.map(|c| mk_struct(cx, c.tys)))
91+
}
92+
}
93+
_ => cx.sess.bug(~"adt::represent_type called on non-ADT type")
94+
}
95+
}
96+
97+
fn mk_struct(cx: @CrateContext, tys: &[ty::t]) -> Struct {
98+
let lltys = tys.map(|&ty| type_of::sizing_type_of(cx, ty));
99+
let llty_rec = T_struct(lltys);
100+
Struct {
101+
size: machine::llsize_of_alloc(cx, llty_rec) /*bad*/as u64,
102+
align: machine::llalign_of_min(cx, llty_rec) /*bad*/as u64,
103+
fields: vec::from_slice(tys)
104+
}
105+
}
106+
107+
108+
pub fn sizing_fields_of(cx: @CrateContext, r: &Repr) -> ~[TypeRef] {
109+
generic_fields_of(cx, r, true)
110+
}
111+
pub fn fields_of(cx: @CrateContext, r: &Repr) -> ~[TypeRef] {
112+
generic_fields_of(cx, r, false)
113+
}
114+
fn generic_fields_of(cx: @CrateContext, r: &Repr, sizing: bool)
115+
-> ~[TypeRef] {
116+
match *r {
117+
CEnum => ~[T_enum_discrim(cx)],
118+
Univariant(ref st, dt) => {
119+
let f = if sizing {
120+
st.fields.map(|&ty| type_of::sizing_type_of(cx, ty))
121+
} else {
122+
st.fields.map(|&ty| type_of::type_of(cx, ty))
123+
};
124+
match dt {
125+
NoDtor => f,
126+
DtorAbsent => ~[T_struct(f)],
127+
DtorPresent => ~[T_struct(f), T_i8()]
128+
}
129+
}
130+
General(ref sts) => {
131+
~[T_enum_discrim(cx),
132+
T_array(T_i8(), sts.map(|st| st.size).max() /*bad*/as uint)]
133+
}
134+
}
135+
}
136+
137+
pub fn trans_switch(bcx: block, r: &Repr, scrutinee: ValueRef) ->
138+
(_match::branch_kind, Option<ValueRef>) {
139+
// XXX: LoadRangeAssert
140+
match *r {
141+
CEnum => {
142+
(_match::switch, Some(Load(bcx, GEPi(bcx, scrutinee, [0, 0]))))
143+
}
144+
Univariant(*) => {
145+
(_match::single, None)
146+
}
147+
General(*) => {
148+
(_match::switch, Some(Load(bcx, GEPi(bcx, scrutinee, [0, 0]))))
149+
}
150+
}
151+
}
152+
153+
pub fn trans_case(bcx: block, r: &Repr, discr: int) -> _match::opt_result {
154+
match *r {
155+
CEnum => {
156+
_match::single_result(rslt(bcx, C_int(bcx.ccx(), discr)))
157+
}
158+
Univariant(*) => {
159+
bcx.ccx().sess.bug(~"no cases for univariants or structs")
160+
}
161+
General(*) => {
162+
_match::single_result(rslt(bcx, C_int(bcx.ccx(), discr)))
163+
}
164+
}
165+
}
166+
167+
pub fn trans_set_discr(bcx: block, r: &Repr, val: ValueRef, discr: int) {
168+
match *r {
169+
CEnum => {
170+
Store(bcx, C_int(bcx.ccx(), discr), GEPi(bcx, val, [0, 0]))
171+
}
172+
Univariant(_, DtorPresent) => {
173+
assert discr == 0;
174+
Store(bcx, C_u8(1), GEPi(bcx, val, [0, 1]))
175+
}
176+
Univariant(*) => {
177+
assert discr == 0;
178+
}
179+
General(*) => {
180+
Store(bcx, C_int(bcx.ccx(), discr), GEPi(bcx, val, [0, 0]))
181+
}
182+
}
183+
}
184+
185+
pub fn num_args(r: &Repr, discr: int) -> uint {
186+
match *r {
187+
CEnum => 0,
188+
Univariant(ref st, _dt) => { assert discr == 0; st.fields.len() }
189+
General(ref cases) => cases[discr as uint].fields.len()
190+
}
191+
}
192+
193+
pub fn trans_GEP(bcx: block, r: &Repr, val: ValueRef, discr: int, ix: uint)
194+
-> ValueRef {
195+
// Note: if this ever needs to generate conditionals (e.g., if we
196+
// decide to do some kind of cdr-coding-like non-unique repr
197+
// someday), it'll need to return a possibly-new bcx as well.
198+
match *r {
199+
CEnum => {
200+
bcx.ccx().sess.bug(~"element access in C-like enum")
201+
}
202+
Univariant(ref st, dt) => {
203+
assert discr == 0;
204+
let val = match dt {
205+
NoDtor => val,
206+
DtorPresent | DtorAbsent => GEPi(bcx, val, [0, 0])
207+
};
208+
struct_GEP(bcx, st, val, ix)
209+
}
210+
General(ref cases) => {
211+
struct_GEP(bcx, &cases[discr as uint],
212+
GEPi(bcx, val, [0, 1]), ix)
213+
}
214+
}
215+
}
216+
217+
fn struct_GEP(bcx: block, st: &Struct, val: ValueRef, ix: uint)
218+
-> ValueRef {
219+
let ccx = bcx.ccx();
220+
221+
let real_llty = T_struct(st.fields.map(
222+
|&ty| type_of::type_of(ccx, ty)));
223+
let cast_val = PointerCast(bcx, val, T_ptr(real_llty));
224+
225+
GEPi(bcx, cast_val, [0, ix])
226+
}
227+
228+
pub fn trans_const(ccx: @CrateContext, r: &Repr, discr: int,
229+
vals: &[ValueRef]) -> ValueRef {
230+
match *r {
231+
CEnum => {
232+
assert vals.len() == 0;
233+
C_int(ccx, discr)
234+
}
235+
Univariant(ref st, _dt) => {
236+
assert discr == 0;
237+
// consts are never destroyed, so the dtor flag is not needed
238+
C_struct(build_const_struct(ccx, st, vals))
239+
}
240+
General(ref cases) => {
241+
let case = &cases[discr as uint];
242+
let max_sz = cases.map(|s| s.size).max();
243+
let body = build_const_struct(ccx, case, vals);
244+
245+
C_struct([C_int(ccx, discr),
246+
C_packed_struct([C_struct(body)]),
247+
padding(max_sz - case.size)])
248+
}
249+
}
250+
}
251+
252+
fn padding(size: u64) -> ValueRef {
253+
C_undef(T_array(T_i8(), size /*bad*/as uint))
254+
}
255+
256+
fn build_const_struct(ccx: @CrateContext, st: &Struct, vals: &[ValueRef])
257+
-> ~[ValueRef] {
258+
assert vals.len() == st.fields.len();
259+
260+
let mut offset = 0;
261+
let mut cfields = ~[];
262+
for st.fields.eachi |i, &ty| {
263+
let llty = type_of::sizing_type_of(ccx, ty);
264+
let type_align = machine::llalign_of_min(ccx, llty)
265+
/*bad*/as u64;
266+
let val_align = machine::llalign_of_min(ccx, val_ty(vals[i]))
267+
/*bad*/as u64;
268+
let target_offset = roundup(offset, type_align);
269+
offset = roundup(offset, val_align);
270+
if (offset != target_offset) {
271+
cfields.push(padding(target_offset - offset));
272+
offset = target_offset;
273+
}
274+
assert !is_undef(vals[i]);
275+
// If that assert fails, could change it to wrap in a struct?
276+
cfields.push(vals[i]);
277+
}
278+
279+
return cfields;
280+
}
281+
282+
#[always_inline]
283+
fn roundup(x: u64, a: u64) -> u64 { ((x + (a - 1)) / a) * a }
284+
285+
286+
pub fn const_get_discrim(ccx: @CrateContext, r: &Repr, val: ValueRef)
287+
-> int {
288+
match *r {
289+
CEnum(*) => const_to_int(val) as int,
290+
Univariant(*) => 0,
291+
General(*) => const_to_int(const_get_elt(ccx, val, [0])) as int,
292+
}
293+
}
294+
295+
pub fn const_get_element(ccx: @CrateContext, r: &Repr, val: ValueRef,
296+
_discr: int, ix: uint) -> ValueRef {
297+
// Not to be confused with common::const_get_elt.
298+
match *r {
299+
CEnum(*) => ccx.sess.bug(~"element access in C-like enum const"),
300+
Univariant(*) => const_struct_field(ccx, val, ix),
301+
General(*) => const_struct_field(ccx, const_get_elt(ccx, val,
302+
[1, 0]), ix)
303+
}
304+
}
305+
306+
fn const_struct_field(ccx: @CrateContext, val: ValueRef, ix: uint)
307+
-> ValueRef {
308+
// Get the ix-th non-undef element of the struct.
309+
let mut real_ix = 0; // actual position in the struct
310+
let mut ix = ix; // logical index relative to real_ix
311+
let mut field;
312+
loop {
313+
loop {
314+
field = const_get_elt(ccx, val, [real_ix]);
315+
if !is_undef(field) {
316+
break;
317+
}
318+
real_ix = real_ix + 1;
319+
}
320+
if ix == 0 {
321+
return field;
322+
}
323+
ix = ix - 1;
324+
real_ix = real_ix + 1;
325+
}
326+
}

0 commit comments

Comments
 (0)