1
Fork 0

Add code for older crate map versions, bumped crate map version number

This commit is contained in:
Florian Hahn 2013-10-01 23:53:56 +02:00
parent 5dd1145c9b
commit b7b4f7a5e2
2 changed files with 172 additions and 39 deletions

View file

@ -3008,7 +3008,7 @@ pub fn fill_crate_map(ccx: &mut CrateContext, map: ValueRef) {
let (mod_map, mod_count, mod_struct_size) = create_module_map(ccx);
llvm::LLVMSetInitializer(map, C_struct(
[C_i32(1),
[C_i32(2),
C_struct([
p2i(ccx, mod_map),
// byte size of the module map array, an entry consists of two integers

View file

@ -8,12 +8,19 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[cfg(not(stage0))] use cast::transmute;
//#[cfg(not(stage0))] use cast::transmute;
use container::MutableSet;
use hashmap::HashSet;
use option::{Some, None};
use vec::ImmutableVector;
/// Imports for old crate map versions
use cast::transmute;
use libc::c_char;
use ptr;
use str::raw::from_c_str;
use vec;
// 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
// the crate_map properly.
@ -28,16 +35,29 @@ extern {
static CRATE_MAP: CrateMap<'static>;
}
/// structs for old crate map versions
pub struct ModEntryV0 {
name: *c_char,
log_level: *mut u32
}
pub struct CrateMapV0 {
entries: *ModEntryV0,
children: [*CrateMapV0, ..1]
}
pub struct CrateMapV1 {
version: i32,
entries: *ModEntryV0,
/// a dynamically sized struct, where all pointers to children are listed adjacent
/// to the struct, terminated with NULL
children: [*CrateMapV1, ..1]
}
pub struct ModEntry<'self> {
name: &'self str,
log_level: *mut u32
}
pub struct CrateMapV0<'self> {
entries: &'self [ModEntry<'self>],
children: &'self [&'self CrateMap<'self>]
}
pub struct CrateMap<'self> {
version: i32,
entries: &'self [ModEntry<'self>],
@ -46,6 +66,8 @@ pub struct CrateMap<'self> {
children: &'self [&'self CrateMap<'self>]
}
#[cfg(not(windows))]
pub fn get_crate_map() -> &'static CrateMap<'static> {
&'static CRATE_MAP
@ -71,51 +93,60 @@ pub fn get_crate_map() -> &'static CrateMap<'static> {
fn version(crate_map: &CrateMap) -> i32 {
match crate_map.version {
2 => return 2,
1 => return 1,
_ => return 0
}
}
#[cfg(not(stage0))]
fn get_entries_and_children<'a>(crate_map: &'a CrateMap<'a>) ->
(&'a [ModEntry<'a>], &'a [&'a CrateMap<'a>]) {
match version(crate_map) {
0 => {
unsafe {
let v0: &'a CrateMapV0<'a> = transmute(crate_map);
return (v0.entries, v0.children);
}
}
1 => return (*crate_map).entries,
_ => fail2!("Unknown crate map version!")
}
}
#[cfg(not(stage0))]
fn iter_module_map(mod_entries: &[ModEntry], f: &fn(&ModEntry)) {
for entry in mod_entries.iter() {
f(entry);
}
}
#[cfg(not(stage0))]
unsafe fn iter_module_map_v0(entries: *ModEntryV0, f: &fn(&ModEntry)) {
let mut curr = entries;
while !(*curr).name.is_null() {
let mod_entry = ModEntry { name: from_c_str((*curr).name), log_level: (*curr).log_level };
f(&mod_entry);
curr = curr.offset(1);
}
}
fn do_iter_crate_map<'a>(crate_map: &'a CrateMap<'a>, f: &fn(&ModEntry),
visited: &mut HashSet<*CrateMap<'a>>) {
if visited.insert(crate_map as *CrateMap) {
let (entries, children) = get_entries_and_children(crate_map);
iter_module_map(entries, |x| f(x));
for child in children.iter() {
do_iter_crate_map(*child, |x| f(x), visited);
match version(crate_map) {
2 => {
let (entries, children) = (crate_map.entries, crate_map.children);
iter_module_map(entries, |x| f(x));
for child in children.iter() {
do_iter_crate_map(*child, |x| f(x), visited);
}
},
/// code for old crate map versions
1 => unsafe {
let v1: *CrateMapV1 = transmute(crate_map);
iter_module_map_v0((*v1).entries, |x| f(x));
let children = vec::raw::to_ptr((*v1).children);
do ptr::array_each(children) |child| {
do_iter_crate_map(transmute(child), |x| f(x), visited);
}
},
0 => unsafe {
let v0: *CrateMapV0 = transmute(crate_map);
iter_module_map_v0((*v0).entries, |x| f(x));
let children = vec::raw::to_ptr((*v0).children);
do ptr::array_each(children) |child| {
do_iter_crate_map(transmute(child), |x| f(x), visited);
}
},
_ => fail2!("invalid crate map version")
}
}
}
#[cfg(stage0)]
/// Iterates recursively over `crate_map` and all child crate maps
pub fn iter_crate_map<'a>(crate_map: &'a CrateMap<'a>, f: &fn(&ModEntry)) {
}
#[cfg(not(stage0))]
/// Iterates recursively over `crate_map` and all child crate maps
pub fn iter_crate_map<'a>(crate_map: &'a CrateMap<'a>, f: &fn(&ModEntry)) {
// XXX: use random numbers as keys from the OS-level RNG when there is a nice
@ -137,13 +168,13 @@ mod tests {
];
let child_crate = CrateMap {
version: 1,
version: 2,
entries: entries,
children: []
};
let root_crate = CrateMap {
version: 1,
version: 2,
entries: [],
children: [&child_crate, &child_crate]
};
@ -163,7 +194,7 @@ mod tests {
let mut level2: u32 = 2;
let mut level3: u32 = 3;
let child_crate2 = CrateMap {
version: 1,
version: 2,
entries: [
ModEntry { name: "c::m1", log_level: &mut level2},
ModEntry { name: "c::m2", log_level: &mut level3},
@ -172,7 +203,7 @@ mod tests {
};
let child_crate1 = CrateMap {
version: 1,
version: 2,
entries: [
ModEntry { name: "t::f1", log_level: &mut 1},
],
@ -180,7 +211,7 @@ mod tests {
};
let root_crate = CrateMap {
version: 1,
version: 2,
entries: [
ModEntry { name: "t::f2", log_level: &mut 0},
],
@ -196,4 +227,106 @@ mod tests {
assert!(cnt == 4);
}
}
/// Tests for old crate map versions
#[test]
fn iter_crate_map_duplicates_v1() {
use c_str::ToCStr;
use cast::transmute;
use ptr;
use rt::crate_map::{CrateMapV1, ModEntryV0, iter_crate_map};
use vec;
struct CrateMapT3 {
version: i32,
entries: *ModEntryV0,
children: [*CrateMapV1, ..3]
}
unsafe {
let mod_name1 = "c::m1".to_c_str();
let mut level3: u32 = 3;
let entries: ~[ModEntryV0] = ~[
ModEntryV0 { name: mod_name1.with_ref(|buf| buf), log_level: &mut level3},
ModEntryV0 { name: ptr::null(), log_level: ptr::mut_null()}
];
let child_crate = CrateMapV1 {
version: 1,
entries: vec::raw::to_ptr(entries),
children: [ptr::null()]
};
let root_crate = CrateMapT3 {
version: 1,
entries: vec::raw::to_ptr([ModEntryV0 { name: ptr::null(), log_level: ptr::mut_null()}]),
children: [&child_crate as *CrateMapV1, &child_crate as *CrateMapV1, ptr::null()]
};
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_v1() {
use c_str::ToCStr;
use cast::transmute;
use ptr;
use rt::crate_map::{CrateMapV1, ModEntryV0, iter_crate_map};
use vec;
struct CrateMapT2 {
version: i32,
entries: *ModEntryV0,
children: [*CrateMapV1, ..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 = CrateMapV1 {
version: 1,
entries: vec::raw::to_ptr([
ModEntryV0 { name: mod_name1.with_ref(|buf| buf), log_level: &mut level2},
ModEntryV0 { name: mod_name2.with_ref(|buf| buf), log_level: &mut level3},
ModEntryV0 { name: ptr::null(), log_level: ptr::mut_null()}
]),
children: [ptr::null()]
};
let child_crate1 = CrateMapT2 {
version: 1,
entries: vec::raw::to_ptr([
ModEntryV0 { name: "t::f1".with_c_str(|buf| buf), log_level: &mut 1},
ModEntryV0 { name: ptr::null(), log_level: ptr::mut_null()}
]),
children: [&child_crate2 as *CrateMapV1, ptr::null()]
};
let child_crate1_ptr: *CrateMapV1 = transmute(&child_crate1);
let root_crate = CrateMapT2 {
version: 1,
entries: vec::raw::to_ptr([
ModEntryV0 { name: "t::f1".with_c_str(|buf| buf), log_level: &mut 0},
ModEntryV0 { 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);
}
}
}