Use slice representation for child crate maps
This commit is contained in:
parent
1506dac10f
commit
787f20a255
@ -2949,6 +2949,7 @@ pub fn create_module_map(ccx: &mut CrateContext) -> ValueRef {
|
|||||||
|
|
||||||
pub fn decl_crate_map(sess: session::Session, mapmeta: LinkMeta,
|
pub fn decl_crate_map(sess: session::Session, mapmeta: LinkMeta,
|
||||||
llmod: ModuleRef) -> ValueRef {
|
llmod: ModuleRef) -> ValueRef {
|
||||||
|
|
||||||
let targ_cfg = sess.targ_cfg;
|
let targ_cfg = sess.targ_cfg;
|
||||||
let int_type = Type::int(targ_cfg.arch);
|
let int_type = Type::int(targ_cfg.arch);
|
||||||
let mut n_subcrates = 1;
|
let mut n_subcrates = 1;
|
||||||
@ -2959,9 +2960,10 @@ pub fn decl_crate_map(sess: session::Session, mapmeta: LinkMeta,
|
|||||||
} else {
|
} else {
|
||||||
~"toplevel"
|
~"toplevel"
|
||||||
};
|
};
|
||||||
|
|
||||||
let sym_name = ~"_rust_crate_map_" + mapname;
|
let sym_name = ~"_rust_crate_map_" + mapname;
|
||||||
let arrtype = Type::array(&int_type, n_subcrates as u64);
|
let vectype = Type::struct_([int_type, int_type], false);
|
||||||
let maptype = Type::struct_([Type::i32(), int_type, arrtype], false);
|
let maptype = Type::struct_([Type::i32(), int_type, vectype], false);
|
||||||
let map = do sym_name.with_c_str |buf| {
|
let map = do sym_name.with_c_str |buf| {
|
||||||
unsafe {
|
unsafe {
|
||||||
llvm::LLVMAddGlobal(llmod, maptype.to_ref(), buf)
|
llvm::LLVMAddGlobal(llmod, maptype.to_ref(), buf)
|
||||||
@ -2996,14 +2998,24 @@ pub fn fill_crate_map(ccx: &mut CrateContext, map: ValueRef) {
|
|||||||
subcrates.push(p2i(ccx, cr));
|
subcrates.push(p2i(ccx, cr));
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
subcrates.push(C_int(ccx, 0));
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
|
let maptype = Type::array(&ccx.int_type, subcrates.len() as u64);
|
||||||
|
let vec_elements = do "_crate_map_child_vectors".with_c_str |buf| {
|
||||||
|
llvm::LLVMAddGlobal(ccx.llmod, maptype.to_ref(), buf)
|
||||||
|
};
|
||||||
|
lib::llvm::SetLinkage(vec_elements, lib::llvm::InternalLinkage);
|
||||||
|
|
||||||
|
llvm::LLVMSetInitializer(vec_elements, C_array(ccx.int_type, subcrates));
|
||||||
let mod_map = create_module_map(ccx);
|
let mod_map = create_module_map(ccx);
|
||||||
|
|
||||||
llvm::LLVMSetInitializer(map, C_struct(
|
llvm::LLVMSetInitializer(map, C_struct(
|
||||||
[C_i32(1),
|
[C_i32(1),
|
||||||
p2i(ccx, mod_map),
|
p2i(ccx, mod_map),
|
||||||
C_array(ccx.int_type, subcrates)]));
|
C_struct(
|
||||||
|
[p2i(ccx, vec_elements),
|
||||||
|
C_int(ccx, (subcrates.len() * 8) as int)
|
||||||
|
])
|
||||||
|
]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,13 +8,10 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
|
use cast::transmute;
|
||||||
use libc::c_char;
|
|
||||||
use ptr;
|
|
||||||
use ptr::RawPtr;
|
|
||||||
use vec;
|
|
||||||
use hashmap::HashSet;
|
|
||||||
use container::MutableSet;
|
use container::MutableSet;
|
||||||
|
use hashmap::HashSet;
|
||||||
|
use libc::c_char;
|
||||||
|
|
||||||
// Need to tell the linker on OS X to not barf on undefined symbols
|
// Need to tell the linker on OS X to not barf on undefined symbols
|
||||||
// and instead look them up at runtime, which we need to resolve
|
// and instead look them up at runtime, which we need to resolve
|
||||||
@ -34,14 +31,15 @@ pub struct ModEntry {
|
|||||||
name: *c_char,
|
name: *c_char,
|
||||||
log_level: *mut u32
|
log_level: *mut u32
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CrateMapV0 {
|
struct CrateMapV0 {
|
||||||
entries: *ModEntry,
|
entries: &static [ModEntry],
|
||||||
children: [*CrateMap, ..1]
|
children: &'static [&'static CrateMap]
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CrateMap {
|
struct CrateMap {
|
||||||
version: i32,
|
version: i32,
|
||||||
entries: *ModEntry,
|
entries: &static [ModEntry],
|
||||||
/// a dynamically sized struct, where all pointers to children are listed adjacent
|
/// a dynamically sized struct, where all pointers to children are listed adjacent
|
||||||
/// to the struct, terminated with NULL
|
/// to the struct, terminated with NULL
|
||||||
children: [*CrateMap, ..1]
|
children: [*CrateMap, ..1]
|
||||||
@ -71,153 +69,175 @@ pub fn get_crate_map() -> *CrateMap {
|
|||||||
sym as *CrateMap
|
sym as *CrateMap
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn version(crate_map: *CrateMap) -> i32 {
|
fn version(crate_map: &'static CrateMap) -> i32 {
|
||||||
match (*crate_map).version {
|
match crate_map.version {
|
||||||
1 => return 1,
|
1 => return 1,
|
||||||
_ => return 0
|
_ => return 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn entries(crate_map: *CrateMap) -> *ModEntry {
|
#[cfg(not(stage0))]
|
||||||
|
fn entries(crate_map: &'static CrateMap) -> *ModEntry {
|
||||||
match version(crate_map) {
|
match version(crate_map) {
|
||||||
0 => {
|
0 => {
|
||||||
let v0 = crate_map as (*CrateMapV0);
|
unsafe {
|
||||||
return (*v0).entries;
|
let v0: &'static CrateMapV0 = transmute(crate_map);
|
||||||
|
return v0.entries;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
1 => return (*crate_map).entries,
|
1 => return (*crate_map).entries,
|
||||||
_ => fail2!("Unknown crate map version!")
|
_ => fail2!("Unknown crate map version!")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn iterator(crate_map: *CrateMap) -> **CrateMap {
|
#[cfg(not(stage0))]
|
||||||
|
fn iterator(crate_map: &'static CrateMap) -> &'static [&'static CrateMap] {
|
||||||
match version(crate_map) {
|
match version(crate_map) {
|
||||||
0 => {
|
0 => {
|
||||||
let v0 = crate_map as (*CrateMapV0);
|
unsafe {
|
||||||
return vec::raw::to_ptr((*v0).children);
|
let v0: &'static CrateMapV0 = transmute(crate_map);
|
||||||
|
return v0.children;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
1 => return vec::raw::to_ptr((*crate_map).children),
|
1 => return vec::raw::to_ptr((*crate_map).children),
|
||||||
_ => fail2!("Unknown crate map version!")
|
_ => fail2!("Unknown crate map version!")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn iter_module_map(mod_entries: *ModEntry, f: &fn(*mut ModEntry)) {
|
fn iter_module_map(mod_entries: *ModEntry, f: &fn(&mut ModEntry)) {
|
||||||
let mut curr = mod_entries;
|
let mut curr = mod_entries;
|
||||||
|
|
||||||
while !(*curr).name.is_null() {
|
unsafe {
|
||||||
f(curr as *mut ModEntry);
|
while !(*curr).name.is_null() {
|
||||||
curr = curr.offset(1);
|
f(transmute(curr));
|
||||||
}
|
curr = curr.offset(1);
|
||||||
}
|
|
||||||
|
|
||||||
unsafe fn do_iter_crate_map(crate_map: *CrateMap, f: &fn(*mut ModEntry),
|
|
||||||
visited: &mut HashSet<*CrateMap>) {
|
|
||||||
if visited.insert(crate_map) {
|
|
||||||
iter_module_map(entries(crate_map), |x| f(x));
|
|
||||||
let child_crates = iterator(crate_map);
|
|
||||||
do ptr::array_each(child_crates) |child| {
|
|
||||||
do_iter_crate_map(child, |x| f(x), visited);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#[cfg(not(stage0))]
|
||||||
|
fn do_iter_crate_map(crate_map: &'static CrateMap, f: &fn(&mut ModEntry),
|
||||||
|
visited: &mut HashSet<*CrateMap>) {
|
||||||
|
if visited.insert(crate_map as *CrateMap) {
|
||||||
|
iter_module_map(crate_map.entries, |x| f(x));
|
||||||
|
let child_crates = iterator(crate_map);
|
||||||
|
|
||||||
|
let mut i = 0;
|
||||||
|
while i < child_crates.len() {
|
||||||
|
do_iter_crate_map(child_crates[i], |x| f(x), visited);
|
||||||
|
i = i + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(stage0)]
|
||||||
/// Iterates recursively over `crate_map` and all child crate maps
|
/// Iterates recursively over `crate_map` and all child crate maps
|
||||||
pub unsafe fn iter_crate_map(crate_map: *CrateMap, f: &fn(*mut ModEntry)) {
|
pub fn iter_crate_map(crate_map: *u8, f: &fn(&mut ModEntry)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(stage0))]
|
||||||
|
/// Iterates recursively over `crate_map` and all child crate maps
|
||||||
|
pub fn iter_crate_map(crate_map: &'static CrateMap, f: &fn(&mut ModEntry)) {
|
||||||
// XXX: use random numbers as keys from the OS-level RNG when there is a nice
|
// XXX: use random numbers as keys from the OS-level RNG when there is a nice
|
||||||
// way to do this
|
// way to do this
|
||||||
let mut v: HashSet<*CrateMap> = HashSet::with_capacity_and_keys(0, 0, 32);
|
let mut v: HashSet<*CrateMap> = HashSet::with_capacity_and_keys(0, 0, 32);
|
||||||
do_iter_crate_map(crate_map, f, &mut v);
|
unsafe {
|
||||||
|
do_iter_crate_map(transmute(crate_map), f, &mut v);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[cfg(test)]
|
||||||
fn iter_crate_map_duplicates() {
|
mod tests {
|
||||||
use c_str::ToCStr;
|
use c_str::ToCStr;
|
||||||
use cast::transmute;
|
use cast::transmute;
|
||||||
|
use ptr;
|
||||||
|
use vec;
|
||||||
|
|
||||||
struct CrateMapT3 {
|
use rt::crate_map::{ModEntry, iter_crate_map};
|
||||||
|
|
||||||
|
struct CrateMap<'self> {
|
||||||
version: i32,
|
version: i32,
|
||||||
entries: *ModEntry,
|
entries: *ModEntry,
|
||||||
children: [*CrateMap, ..3]
|
/// a dynamically sized struct, where all pointers to children are listed adjacent
|
||||||
|
/// to the struct, terminated with NULL
|
||||||
|
children: &'self [&'self CrateMap<'self>]
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe {
|
#[test]
|
||||||
let mod_name1 = "c::m1".to_c_str();
|
fn iter_crate_map_duplicates() {
|
||||||
let mut level3: u32 = 3;
|
unsafe {
|
||||||
|
let mod_name1 = "c::m1".to_c_str();
|
||||||
|
let mut level3: u32 = 3;
|
||||||
|
|
||||||
let entries: ~[ModEntry] = ~[
|
let entries: ~[ModEntry] = ~[
|
||||||
ModEntry { name: mod_name1.with_ref(|buf| buf), log_level: &mut level3},
|
ModEntry { name: mod_name1.with_ref(|buf| buf), log_level: &mut level3},
|
||||||
ModEntry { name: ptr::null(), log_level: ptr::mut_null()}
|
ModEntry { name: ptr::null(), log_level: ptr::mut_null()}
|
||||||
];
|
];
|
||||||
let child_crate = CrateMap {
|
|
||||||
version: 1,
|
|
||||||
entries: vec::raw::to_ptr(entries),
|
|
||||||
children: [ptr::null()]
|
|
||||||
};
|
|
||||||
|
|
||||||
let root_crate = CrateMapT3 {
|
let child_crate = CrateMap {
|
||||||
version: 1,
|
version: 1,
|
||||||
entries: vec::raw::to_ptr([ModEntry { name: ptr::null(), log_level: ptr::mut_null()}]),
|
entries: vec::raw::to_ptr(entries),
|
||||||
children: [&child_crate as *CrateMap, &child_crate as *CrateMap, ptr::null()]
|
children: []
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut cnt = 0;
|
let root_crate = CrateMap {
|
||||||
do iter_crate_map(transmute(&root_crate)) |entry| {
|
version: 1,
|
||||||
assert!(*(*entry).log_level == 3);
|
entries: vec::raw::to_ptr([ModEntry { name: ptr::null(), log_level: ptr::mut_null()}]),
|
||||||
cnt += 1;
|
children: [&child_crate, &child_crate]
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut cnt = 0;
|
||||||
|
do iter_crate_map(transmute(&root_crate)) |entry| {
|
||||||
|
assert!(*entry.log_level == 3);
|
||||||
|
cnt += 1;
|
||||||
|
}
|
||||||
|
assert!(cnt == 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn iter_crate_map_follow_children() {
|
||||||
|
unsafe {
|
||||||
|
let mod_name1 = "c::m1".to_c_str();
|
||||||
|
let mod_name2 = "c::m2".to_c_str();
|
||||||
|
let mut level2: u32 = 2;
|
||||||
|
let mut level3: u32 = 3;
|
||||||
|
let child_crate2 = CrateMap {
|
||||||
|
version: 1,
|
||||||
|
entries: vec::raw::to_ptr([
|
||||||
|
ModEntry { name: mod_name1.with_ref(|buf| buf), log_level: &mut level2},
|
||||||
|
ModEntry { name: mod_name2.with_ref(|buf| buf), log_level: &mut level3},
|
||||||
|
ModEntry { name: ptr::null(), log_level: ptr::mut_null()}
|
||||||
|
]),
|
||||||
|
children: []
|
||||||
|
};
|
||||||
|
|
||||||
|
let child_crate1 = CrateMap {
|
||||||
|
version: 1,
|
||||||
|
entries: vec::raw::to_ptr([
|
||||||
|
ModEntry { name: "t::f1".to_c_str().with_ref(|buf| buf), log_level: &mut 1},
|
||||||
|
ModEntry { name: ptr::null(), log_level: ptr::mut_null()}
|
||||||
|
]),
|
||||||
|
children: [&child_crate2]
|
||||||
|
};
|
||||||
|
|
||||||
|
let root_crate = CrateMap {
|
||||||
|
version: 1,
|
||||||
|
entries: vec::raw::to_ptr([
|
||||||
|
ModEntry { name: "t::f1".to_c_str().with_ref(|buf| buf), log_level: &mut 0},
|
||||||
|
ModEntry { name: ptr::null(), log_level: ptr::mut_null()}
|
||||||
|
]),
|
||||||
|
children: [&child_crate1]
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut cnt = 0;
|
||||||
|
do iter_crate_map(transmute(&root_crate)) |entry| {
|
||||||
|
assert!(*entry.log_level == cnt);
|
||||||
|
cnt += 1;
|
||||||
|
}
|
||||||
|
assert!(cnt == 4);
|
||||||
}
|
}
|
||||||
assert!(cnt == 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn iter_crate_map_follow_children() {
|
|
||||||
use c_str::ToCStr;
|
|
||||||
use cast::transmute;
|
|
||||||
|
|
||||||
struct CrateMapT2 {
|
|
||||||
version: i32,
|
|
||||||
entries: *ModEntry,
|
|
||||||
children: [*CrateMap, ..2]
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
let mod_name1 = "c::m1".to_c_str();
|
|
||||||
let mod_name2 = "c::m2".to_c_str();
|
|
||||||
let mut level2: u32 = 2;
|
|
||||||
let mut level3: u32 = 3;
|
|
||||||
let child_crate2 = CrateMap {
|
|
||||||
version: 1,
|
|
||||||
entries: vec::raw::to_ptr([
|
|
||||||
ModEntry { name: mod_name1.with_ref(|buf| buf), log_level: &mut level2},
|
|
||||||
ModEntry { name: mod_name2.with_ref(|buf| buf), log_level: &mut level3},
|
|
||||||
ModEntry { name: ptr::null(), log_level: ptr::mut_null()}
|
|
||||||
]),
|
|
||||||
children: [ptr::null()]
|
|
||||||
};
|
|
||||||
|
|
||||||
let child_crate1 = CrateMapT2 {
|
|
||||||
version: 1,
|
|
||||||
entries: vec::raw::to_ptr([
|
|
||||||
ModEntry { name: "t::f1".with_c_str(|buf| buf), log_level: &mut 1},
|
|
||||||
ModEntry { name: ptr::null(), log_level: ptr::mut_null()}
|
|
||||||
]),
|
|
||||||
children: [&child_crate2 as *CrateMap, ptr::null()]
|
|
||||||
};
|
|
||||||
|
|
||||||
let child_crate1_ptr: *CrateMap = transmute(&child_crate1);
|
|
||||||
let root_crate = CrateMapT2 {
|
|
||||||
version: 1,
|
|
||||||
entries: vec::raw::to_ptr([
|
|
||||||
ModEntry { name: "t::f1".with_c_str(|buf| buf), log_level: &mut 0},
|
|
||||||
ModEntry { name: ptr::null(), log_level: ptr::mut_null()}
|
|
||||||
]),
|
|
||||||
children: [child_crate1_ptr, ptr::null()]
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut cnt = 0;
|
|
||||||
do iter_crate_map(transmute(&root_crate)) |entry| {
|
|
||||||
assert!(*(*entry).log_level == cnt);
|
|
||||||
cnt += 1;
|
|
||||||
}
|
|
||||||
assert!(cnt == 4);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@ use str::StrSlice;
|
|||||||
use str::raw::from_c_str;
|
use str::raw::from_c_str;
|
||||||
use u32;
|
use u32;
|
||||||
use vec::ImmutableVector;
|
use vec::ImmutableVector;
|
||||||
|
use send_str::{SendStr, SendStrOwned, SendStrStatic};
|
||||||
use cast::transmute;
|
use cast::transmute;
|
||||||
|
|
||||||
struct LogDirective {
|
struct LogDirective {
|
||||||
@ -110,7 +111,7 @@ fn parse_logging_spec(spec: ~str) -> ~[LogDirective]{
|
|||||||
|
|
||||||
/// Set the log level of an entry in the crate map depending on the vector
|
/// Set the log level of an entry in the crate map depending on the vector
|
||||||
/// of log directives
|
/// of log directives
|
||||||
fn update_entry(dirs: &[LogDirective], entry: *mut ModEntry) -> u32 {
|
fn update_entry(dirs: &[LogDirective], entry: &mut ModEntry) -> u32 {
|
||||||
let mut new_lvl: u32 = DEFAULT_LOG_LEVEL;
|
let mut new_lvl: u32 = DEFAULT_LOG_LEVEL;
|
||||||
let mut longest_match = -1i;
|
let mut longest_match = -1i;
|
||||||
unsafe {
|
unsafe {
|
||||||
@ -123,7 +124,7 @@ fn update_entry(dirs: &[LogDirective], entry: *mut ModEntry) -> u32 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(ref dir_name) => {
|
Some(ref dir_name) => {
|
||||||
let name = from_c_str((*entry).name);
|
let name = from_c_str(entry.name);
|
||||||
let len = dir_name.len() as int;
|
let len = dir_name.len() as int;
|
||||||
if name.starts_with(*dir_name) &&
|
if name.starts_with(*dir_name) &&
|
||||||
len >= longest_match {
|
len >= longest_match {
|
||||||
@ -133,7 +134,7 @@ fn update_entry(dirs: &[LogDirective], entry: *mut ModEntry) -> u32 {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
*(*entry).log_level = new_lvl;
|
*entry.log_level = new_lvl;
|
||||||
}
|
}
|
||||||
if longest_match >= 0 { return 1; } else { return 0; }
|
if longest_match >= 0 { return 1; } else { return 0; }
|
||||||
}
|
}
|
||||||
@ -147,8 +148,8 @@ fn update_log_settings(crate_map: *u8, settings: ~str) {
|
|||||||
if settings == ~"::help" || settings == ~"?" {
|
if settings == ~"::help" || settings == ~"?" {
|
||||||
dumb_println("\nCrate log map:\n");
|
dumb_println("\nCrate log map:\n");
|
||||||
unsafe {
|
unsafe {
|
||||||
do iter_crate_map(transmute(crate_map)) |entry: *mut ModEntry| {
|
do iter_crate_map(crate_map) |entry| {
|
||||||
dumb_println(" "+from_c_str((*entry).name));
|
dumb_println(" "+from_c_str(entry.name));
|
||||||
}
|
}
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
@ -157,11 +158,9 @@ fn update_log_settings(crate_map: *u8, settings: ~str) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut n_matches: u32 = 0;
|
let mut n_matches: u32 = 0;
|
||||||
unsafe {
|
do iter_crate_map(crate_map) |entry| {
|
||||||
do iter_crate_map(transmute(crate_map)) |entry: *mut ModEntry| {
|
let m = update_entry(dirs, entry);
|
||||||
let m = update_entry(dirs, entry);
|
n_matches += m;
|
||||||
n_matches += m;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if n_matches < (dirs.len() as u32) {
|
if n_matches < (dirs.len() as u32) {
|
||||||
|
Loading…
Reference in New Issue
Block a user