Skip to content

Commit aaab906

Browse files
committed
---
yaml --- r: 151353 b: refs/heads/try2 c: 2fc3b3a h: refs/heads/master i: 151351: 0bf7e42 v: v3
1 parent 6bb5892 commit aaab906

File tree

27 files changed

+195
-615
lines changed

27 files changed

+195
-615
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ refs/heads/snap-stage3: 78a7676898d9f80ab540c6df5d4c9ce35bb50463
55
refs/heads/try: 519addf6277dbafccbb4159db4b710c37eaa2ec5
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
77
refs/heads/ndm: f3868061cd7988080c30d6d5bf352a5a5fe2460b
8-
refs/heads/try2: 2dcbad5bc40b3ef7d1150db12fba1d653b1c3b16
8+
refs/heads/try2: 2fc3b3a48fef92f9c38d936eed14453a640df0ec
99
refs/heads/dist-snap: ba4081a5a8573875fed17545846f6f6902c8ba8d
1010
refs/tags/release-0.2: c870d2dffb391e14efb05aa27898f1f6333a9596
1111
refs/tags/release-0.3: b5f0d0f648d9a6153664837026ba1be43d3e2503

branches/try2/src/libcollections/bitv.rs

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,32 @@ enum BitvVariant { Big(BigBitv), Small(SmallBitv) }
225225
enum Op {Union, Intersect, Assign, Difference}
226226

227227
/// The bitvector type
228+
///
229+
/// # Example
230+
///
231+
/// ```rust
232+
/// use collections::bitv::Bitv;
233+
///
234+
/// let mut bv = Bitv::new(10, false);
235+
///
236+
/// // insert all primes less than 10
237+
/// bv.set(2, true);
238+
/// bv.set(3, true);
239+
/// bv.set(5, true);
240+
/// bv.set(7, true);
241+
/// println!("{}", bv.to_str());
242+
/// println!("total bits set to true: {}", bv.iter().count(|x| x));
243+
///
244+
/// // flip all values in bitvector, producing non-primes less than 10
245+
/// bv.negate();
246+
/// println!("{}", bv.to_str());
247+
/// println!("total bits set to true: {}", bv.iter().count(|x| x));
248+
///
249+
/// // reset bitvector to empty
250+
/// bv.clear();
251+
/// println!("{}", bv.to_str());
252+
/// println!("total bits set to true: {}", bv.iter().count(|x| x));
253+
/// ```
228254
#[deriving(Clone)]
229255
pub struct Bitv {
230256
/// Internal representation of the bit vector (small or large)
@@ -264,10 +290,11 @@ impl Bitv {
264290
}
265291
}
266292
}
267-
268293
}
269294

270295
impl Bitv {
296+
/// Creates an empty Bitv that holds `nbits` elements, setting each element
297+
/// to `init`.
271298
pub fn new(nbits: uint, init: bool) -> Bitv {
272299
let rep = if nbits < uint::BITS {
273300
Small(SmallBitv::new(if init {(1<<nbits)-1} else {0}))
@@ -419,6 +446,21 @@ impl Bitv {
419446
}
420447
}
421448

449+
/// Returns an iterator over the elements of the vector in order.
450+
///
451+
/// # Example
452+
///
453+
/// ```rust
454+
/// use collections::bitv::Bitv;
455+
/// let mut bv = Bitv::new(10, false);
456+
/// bv.set(1, true);
457+
/// bv.set(2, true);
458+
/// bv.set(3, true);
459+
/// bv.set(5, true);
460+
/// bv.set(8, true);
461+
/// // Count bits set to 1; result should be 5
462+
/// println!("{}", bv.iter().count(|x| x));
463+
/// ```
422464
#[inline]
423465
pub fn iter<'a>(&'a self) -> Bits<'a> {
424466
Bits {bitv: self, next_idx: 0, end_idx: self.nbits}

branches/try2/src/librustc/back/link.rs

Lines changed: 133 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -884,10 +884,10 @@ fn link_binary_output(sess: &Session,
884884
link_staticlib(sess, &obj_filename, &out_filename);
885885
}
886886
session::CrateTypeExecutable => {
887-
link_natively(sess, trans, false, &obj_filename, &out_filename);
887+
link_natively(sess, false, &obj_filename, &out_filename);
888888
}
889889
session::CrateTypeDylib => {
890-
link_natively(sess, trans, true, &obj_filename, &out_filename);
890+
link_natively(sess, true, &obj_filename, &out_filename);
891891
}
892892
}
893893

@@ -1037,13 +1037,13 @@ fn link_staticlib(sess: &Session, obj_filename: &Path, out_filename: &Path) {
10371037
//
10381038
// This will invoke the system linker/cc to create the resulting file. This
10391039
// links to all upstream files as well.
1040-
fn link_natively(sess: &Session, trans: &CrateTranslation, dylib: bool,
1041-
obj_filename: &Path, out_filename: &Path) {
1040+
fn link_natively(sess: &Session, dylib: bool, obj_filename: &Path,
1041+
out_filename: &Path) {
10421042
let tmpdir = TempDir::new("rustc").expect("needs a temp dir");
10431043
// The invocations of cc share some flags across platforms
10441044
let cc_prog = get_cc_prog(sess);
10451045
let mut cc_args = sess.targ_cfg.target_strs.cc_args.clone();
1046-
cc_args.push_all_move(link_args(sess, dylib, tmpdir.path(), trans,
1046+
cc_args.push_all_move(link_args(sess, dylib, tmpdir.path(),
10471047
obj_filename, out_filename));
10481048
if (sess.opts.debugging_opts & session::PRINT_LINK_ARGS) != 0 {
10491049
println!("{} link args: '{}'", cc_prog, cc_args.connect("' '"));
@@ -1092,7 +1092,6 @@ fn link_natively(sess: &Session, trans: &CrateTranslation, dylib: bool,
10921092
fn link_args(sess: &Session,
10931093
dylib: bool,
10941094
tmpdir: &Path,
1095-
trans: &CrateTranslation,
10961095
obj_filename: &Path,
10971096
out_filename: &Path) -> Vec<~str> {
10981097

@@ -1252,7 +1251,7 @@ fn link_args(sess: &Session,
12521251
// this kind of behavior is pretty platform specific and generally not
12531252
// recommended anyway, so I don't think we're shooting ourself in the foot
12541253
// much with that.
1255-
add_upstream_rust_crates(&mut args, sess, dylib, tmpdir, trans);
1254+
add_upstream_rust_crates(&mut args, sess, dylib, tmpdir);
12561255
add_local_native_libraries(&mut args, sess);
12571256
add_upstream_native_libraries(&mut args, sess);
12581257

@@ -1362,44 +1361,73 @@ fn add_local_native_libraries(args: &mut Vec<~str>, sess: &Session) {
13621361
// dependencies will be linked when producing the final output (instead of
13631362
// the intermediate rlib version)
13641363
fn add_upstream_rust_crates(args: &mut Vec<~str>, sess: &Session,
1365-
dylib: bool, tmpdir: &Path,
1366-
trans: &CrateTranslation) {
1367-
// All of the heavy lifting has previously been accomplished by the
1368-
// dependency_format module of the compiler. This is just crawling the
1369-
// output of that module, adding crates as necessary.
1364+
dylib: bool, tmpdir: &Path) {
1365+
1366+
// As a limitation of the current implementation, we require that everything
1367+
// must be static or everything must be dynamic. The reasons for this are a
1368+
// little subtle, but as with staticlibs and rlibs, the goal is to prevent
1369+
// duplicate copies of the same library showing up. For example, a static
1370+
// immediate dependency might show up as an upstream dynamic dependency and
1371+
// we currently have no way of knowing that. We know that all dynamic
1372+
// libraries require dynamic dependencies (see above), so it's satisfactory
1373+
// to include either all static libraries or all dynamic libraries.
13701374
//
1371-
// Linking to a rlib involves just passing it to the linker (the linker
1372-
// will slurp up the object files inside), and linking to a dynamic library
1373-
// involves just passing the right -l flag.
1375+
// With this limitation, we expose a compiler default linkage type and an
1376+
// option to reverse that preference. The current behavior looks like:
1377+
//
1378+
// * If a dylib is being created, upstream dependencies must be dylibs
1379+
// * If nothing else is specified, static linking is preferred
1380+
// * If the -C prefer-dynamic flag is given, dynamic linking is preferred
1381+
// * If one form of linking fails, the second is also attempted
1382+
// * If both forms fail, then we emit an error message
1383+
1384+
let dynamic = get_deps(&sess.cstore, cstore::RequireDynamic);
1385+
let statik = get_deps(&sess.cstore, cstore::RequireStatic);
1386+
match (dynamic, statik, sess.opts.cg.prefer_dynamic, dylib) {
1387+
(_, Some(deps), false, false) => {
1388+
add_static_crates(args, sess, tmpdir, deps)
1389+
}
13741390

1375-
let data = if dylib {
1376-
trans.crate_formats.get(&session::CrateTypeDylib)
1377-
} else {
1378-
trans.crate_formats.get(&session::CrateTypeExecutable)
1379-
};
1391+
(None, Some(deps), true, false) => {
1392+
// If you opted in to dynamic linking and we decided to emit a
1393+
// static output, you should probably be notified of such an event!
1394+
sess.warn("dynamic linking was preferred, but dependencies \
1395+
could not all be found in a dylib format.");
1396+
sess.warn("linking statically instead, using rlibs");
1397+
add_static_crates(args, sess, tmpdir, deps)
1398+
}
13801399

1381-
// Invoke get_used_crates to ensure that we get a topological sorting of
1382-
// crates.
1383-
let deps = sess.cstore.get_used_crates(cstore::RequireDynamic);
1384-
1385-
for &(cnum, _) in deps.iter() {
1386-
// We may not pass all crates through to the linker. Some crates may
1387-
// appear statically in an existing dylib, meaning we'll pick up all the
1388-
// symbols from the dylib.
1389-
let kind = match *data.get(cnum as uint - 1) {
1390-
Some(t) => t,
1391-
None => continue
1392-
};
1393-
let src = sess.cstore.get_used_crate_source(cnum).unwrap();
1394-
match kind {
1395-
cstore::RequireDynamic => {
1396-
add_dynamic_crate(args, sess, src.dylib.unwrap())
1397-
}
1398-
cstore::RequireStatic => {
1399-
add_static_crate(args, sess, tmpdir, cnum, src.rlib.unwrap())
1400+
(Some(deps), _, _, _) => add_dynamic_crates(args, sess, deps),
1401+
1402+
(None, _, _, true) => {
1403+
sess.err("dylib output requested, but some depenencies could not \
1404+
be found in the dylib format");
1405+
let deps = sess.cstore.get_used_crates(cstore::RequireDynamic);
1406+
for (cnum, path) in deps.move_iter() {
1407+
if path.is_some() { continue }
1408+
let name = sess.cstore.get_crate_data(cnum).name.clone();
1409+
sess.note(format!("dylib not found: {}", name));
14001410
}
14011411
}
14021412

1413+
(None, None, pref, false) => {
1414+
let (pref, name) = if pref {
1415+
sess.err("dynamic linking is preferred, but dependencies were \
1416+
not found in either dylib or rlib format");
1417+
(cstore::RequireDynamic, "dylib")
1418+
} else {
1419+
sess.err("dependencies were not all found in either dylib or \
1420+
rlib format");
1421+
(cstore::RequireStatic, "rlib")
1422+
};
1423+
sess.note(format!("dependencies not found in the `{}` format",
1424+
name));
1425+
for (cnum, path) in sess.cstore.get_used_crates(pref).move_iter() {
1426+
if path.is_some() { continue }
1427+
let name = sess.cstore.get_crate_data(cnum).name.clone();
1428+
sess.note(name);
1429+
}
1430+
}
14031431
}
14041432

14051433
// Converts a library file-stem into a cc -l argument
@@ -1411,64 +1439,82 @@ fn add_upstream_rust_crates(args: &mut Vec<~str>, sess: &Session,
14111439
}
14121440
}
14131441

1442+
// Attempts to find all dependencies with a certain linkage preference,
1443+
// returning `None` if not all libraries could be found with that
1444+
// preference.
1445+
fn get_deps(cstore: &cstore::CStore, preference: cstore::LinkagePreference)
1446+
-> Option<Vec<(ast::CrateNum, Path)> >
1447+
{
1448+
let crates = cstore.get_used_crates(preference);
1449+
if crates.iter().all(|&(_, ref p)| p.is_some()) {
1450+
Some(crates.move_iter().map(|(a, b)| (a, b.unwrap())).collect())
1451+
} else {
1452+
None
1453+
}
1454+
}
1455+
14141456
// Adds the static "rlib" versions of all crates to the command line.
1415-
fn add_static_crate(args: &mut Vec<~str>, sess: &Session, tmpdir: &Path,
1416-
cnum: ast::CrateNum, cratepath: Path) {
1417-
// When performing LTO on an executable output, all of the
1418-
// bytecode from the upstream libraries has already been
1419-
// included in our object file output. We need to modify all of
1420-
// the upstream archives to remove their corresponding object
1421-
// file to make sure we don't pull the same code in twice.
1422-
//
1423-
// We must continue to link to the upstream archives to be sure
1424-
// to pull in native static dependencies. As the final caveat,
1425-
// on linux it is apparently illegal to link to a blank archive,
1426-
// so if an archive no longer has any object files in it after
1427-
// we remove `lib.o`, then don't link against it at all.
1428-
//
1429-
// If we're not doing LTO, then our job is simply to just link
1430-
// against the archive.
1431-
if sess.lto() {
1432-
let name = sess.cstore.get_crate_data(cnum).name.clone();
1433-
time(sess.time_passes(), format!("altering {}.rlib", name),
1434-
(), |()| {
1435-
let dst = tmpdir.join(cratepath.filename().unwrap());
1436-
match fs::copy(&cratepath, &dst) {
1437-
Ok(..) => {}
1438-
Err(e) => {
1439-
sess.err(format!("failed to copy {} to {}: {}",
1440-
cratepath.display(),
1441-
dst.display(),
1442-
e));
1443-
sess.abort_if_errors();
1457+
fn add_static_crates(args: &mut Vec<~str>, sess: &Session, tmpdir: &Path,
1458+
crates: Vec<(ast::CrateNum, Path)>) {
1459+
for (cnum, cratepath) in crates.move_iter() {
1460+
// When performing LTO on an executable output, all of the
1461+
// bytecode from the upstream libraries has already been
1462+
// included in our object file output. We need to modify all of
1463+
// the upstream archives to remove their corresponding object
1464+
// file to make sure we don't pull the same code in twice.
1465+
//
1466+
// We must continue to link to the upstream archives to be sure
1467+
// to pull in native static dependencies. As the final caveat,
1468+
// on linux it is apparently illegal to link to a blank archive,
1469+
// so if an archive no longer has any object files in it after
1470+
// we remove `lib.o`, then don't link against it at all.
1471+
//
1472+
// If we're not doing LTO, then our job is simply to just link
1473+
// against the archive.
1474+
if sess.lto() {
1475+
let name = sess.cstore.get_crate_data(cnum).name.clone();
1476+
time(sess.time_passes(), format!("altering {}.rlib", name),
1477+
(), |()| {
1478+
let dst = tmpdir.join(cratepath.filename().unwrap());
1479+
match fs::copy(&cratepath, &dst) {
1480+
Ok(..) => {}
1481+
Err(e) => {
1482+
sess.err(format!("failed to copy {} to {}: {}",
1483+
cratepath.display(),
1484+
dst.display(),
1485+
e));
1486+
sess.abort_if_errors();
1487+
}
14441488
}
1445-
}
1446-
let dst_str = dst.as_str().unwrap().to_owned();
1447-
let mut archive = Archive::open(sess, dst);
1448-
archive.remove_file(format!("{}.o", name));
1449-
let files = archive.files();
1450-
if files.iter().any(|s| s.ends_with(".o")) {
1451-
args.push(dst_str);
1452-
}
1453-
});
1454-
} else {
1455-
args.push(cratepath.as_str().unwrap().to_owned());
1489+
let dst_str = dst.as_str().unwrap().to_owned();
1490+
let mut archive = Archive::open(sess, dst);
1491+
archive.remove_file(format!("{}.o", name));
1492+
let files = archive.files();
1493+
if files.iter().any(|s| s.ends_with(".o")) {
1494+
args.push(dst_str);
1495+
}
1496+
});
1497+
} else {
1498+
args.push(cratepath.as_str().unwrap().to_owned());
1499+
}
14561500
}
14571501
}
14581502

14591503
// Same thing as above, but for dynamic crates instead of static crates.
1460-
fn add_dynamic_crate(args: &mut Vec<~str>, sess: &Session,
1461-
cratepath: Path) {
1504+
fn add_dynamic_crates(args: &mut Vec<~str>, sess: &Session,
1505+
crates: Vec<(ast::CrateNum, Path)> ) {
14621506
// If we're performing LTO, then it should have been previously required
14631507
// that all upstream rust dependencies were available in an rlib format.
14641508
assert!(!sess.lto());
14651509

1466-
// Just need to tell the linker about where the library lives and
1467-
// what its name is
1468-
let dir = cratepath.dirname_str().unwrap();
1469-
if !dir.is_empty() { args.push("-L" + dir); }
1470-
let libarg = unlib(&sess.targ_cfg, cratepath.filestem_str().unwrap());
1471-
args.push("-l" + libarg);
1510+
for (_, cratepath) in crates.move_iter() {
1511+
// Just need to tell the linker about where the library lives and
1512+
// what its name is
1513+
let dir = cratepath.dirname_str().unwrap();
1514+
if !dir.is_empty() { args.push("-L" + dir); }
1515+
let libarg = unlib(&sess.targ_cfg, cratepath.filestem_str().unwrap());
1516+
args.push("-l" + libarg);
1517+
}
14721518
}
14731519
}
14741520

0 commit comments

Comments
 (0)