Commit 85da4191 authored by Isaac Oscar Gariano's avatar Isaac Oscar Gariano

Updated name handling (but only on x86-64)

parent d91898d5
......@@ -521,10 +521,7 @@ pub struct CallData {
impl CallData {
fn debug_str(&self, ops: &Vec<P<TreeNode>>) -> String {
let func_name = match ops[self.func].name() {
Some(name) => name,
None => "Anonymous Function".to_string()
};
let func_name = ops[self.func].name();
format!("{:?} {} [{}]", self.convention, func_name, op_vector_str(&self.args, ops))
}
}
......
......@@ -386,7 +386,7 @@ impl FunctionContent {
pub fn get_block_by_name(&self, name: String) -> &Block {
for block in self.blocks.values() {
if block.name().unwrap() == name {
if block.name() == name {
return block;
}
}
......@@ -1108,7 +1108,7 @@ rodal_struct!(MuEntityHeader{id, name});
#[derive(Debug)] // Display, PartialEq, Clone
pub struct MuEntityHeader {
id: MuID,
name: Option<MuName>
name: MuName
}
impl Clone for MuEntityHeader {
......@@ -1120,62 +1120,98 @@ impl Clone for MuEntityHeader {
}
}
pub fn name_check(name: MuName) -> MuName {
let name = name.replace('.', "$");
/// Returns true if name is a valid_c identifier
/// (i.e. it contains only ASCII letters, digits and underscores
/// and does not start with "__" or an digit.
pub fn is_valid_c_identifier(name: &MuName) -> bool {
let mut i = 0;
let mut underscore = false; // whether the first character is an underscore
for c in name.chars() {
match c {
'_' => {
if i == 0 { underscore = true; }
else if i == 1 && underscore { return false; }
},
'0'...'9' => {
if i == 0 { return false; }
},
'a'...'z' | 'A' ... 'Z' => { }
_ => { return false; }
}
i += 1;
}
return true;
}
// change mangle_name to mangle name
// This will always return a valid C identifier
pub fn mangle_name(name: MuName) -> MuName {
let name = name.replace('@', "");
if name.starts_with("__mu_") {
// TODO: Get rid of this, since it will be trigered if a client provides a name starting with "__mu"
// which is totally valid, it's only here for the moment to debug name handling
panic!("Trying to mangle \"{}\", which is allready mangled", name.clone());
}
if name.starts_with("@") || name.starts_with("%") {
let (_, name) = name.split_at(1);
assert!(!name.starts_with("%"));
return name.to_string();
}
// Note: a ':' and '#' is only used by names generated by zebu itself
let name = name.replace('Z', "ZZ").replace('.', "Zd").replace('-', "Zh").replace(':', "Zc").replace('#', "Za");
"__mu_".to_string() + name.as_str()
}
// WARNING: This only reverses mangle_name above when no warning is issued)
pub fn demangle_name(name: MuName) -> MuName {
if name.starts_with("%") {
panic!("The name '{}'' is local", name);
}
if !name.starts_with("__mu_") {
panic!("Trying to demangle \"{}\", which is not mangled", name.clone());
}
let name = name.split_at("__mu_".len()).1.to_string();
let name = name.replace("Za", "#").replace("Zc", ":").replace("Zh", "-").replace("Zd", ".").replace("ZZ", "Z");
name
}
impl MuEntityHeader {
pub fn unnamed(id: MuID) -> MuEntityHeader {
MuEntityHeader {
id: id,
name: None
name: format!("#{}", id)
}
}
pub fn named(id: MuID, name: MuName) -> MuEntityHeader {
MuEntityHeader {
id: id,
name: Some(name_check(name))
name: name.replace('@', "")
}
}
pub fn id(&self) -> MuID {
self.id
}
pub fn name(&self) -> Option<MuName> {
pub fn name(&self) -> MuName {
self.name.clone()
}
fn abbreviate_name(&self) -> Option<MuName> {
match self.name() {
Some(name) => {
let split: Vec<&str> = name.split('$').collect();
fn abbreviate_name(&self) -> MuName {
let split: Vec<&str> = self.name.split('.').collect();
let mut ret = "".to_string();
let mut ret = "".to_string();
for i in 0..split.len() - 1 {
ret.push(match split[i].chars().next() {
Some(c) => c,
None => '_'
});
ret.push('.');
}
for i in 0..split.len() - 1 {
ret.push(match split[i].chars().next() {
Some(c) => c,
None => '_'
});
ret.push('.');
}
ret.push_str(split.last().unwrap());
ret.push_str(split.last().unwrap());
Some(ret)
}
None => None
}
ret
}
pub fn clone_with_id(&self, new_id: MuID) -> MuEntityHeader {
......@@ -1195,24 +1231,16 @@ impl PartialEq for MuEntityHeader {
impl fmt::Display for MuEntityHeader {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if DISPLAY_ID {
if self.name().is_none() {
write!(f, "{}", self.id)
if PRINT_ABBREVIATE_NAME {
write!(f, "{} #{}", self.abbreviate_name(), self.id)
} else {
if PRINT_ABBREVIATE_NAME {
write!(f, "{} #{}", self.abbreviate_name().unwrap(), self.id)
} else {
write!(f, "{} #{}", self.name().unwrap(), self.id)
}
write!(f, "{} #{}", self.name(), self.id)
}
} else {
if self.name().is_none() {
write!(f, "{}", self.id)
if PRINT_ABBREVIATE_NAME {
write!(f, "{}", self.abbreviate_name())
} else {
if PRINT_ABBREVIATE_NAME {
write!(f, "{}", self.abbreviate_name().unwrap())
} else {
write!(f, "{}", self.name().unwrap())
}
write!(f, "{}", self.name())
}
}
}
......@@ -1220,7 +1248,7 @@ impl fmt::Display for MuEntityHeader {
pub trait MuEntity {
fn id(&self) -> MuID;
fn name(&self) -> Option<MuName>;
fn name(&self) -> MuName;
fn as_entity(&self) -> &MuEntity;
}
......@@ -1239,7 +1267,7 @@ impl MuEntity for TreeNode {
}
}
fn name(&self) -> Option<MuName> {
fn name(&self) -> MuName {
match self.v {
TreeNode_::Instruction(ref inst) => inst.name(),
TreeNode_::Value(ref pv) => pv.name()
......@@ -1264,4 +1292,4 @@ pub fn op_vector_str(vec: &Vec<OpIndex>, ops: &Vec<P<TreeNode>>) -> String {
}
}
ret
}
}
\ No newline at end of file
......@@ -14,6 +14,8 @@
#[macro_use]
extern crate rodal;
#[macro_use]
extern crate log;
extern crate simple_logger;
#[macro_use]
extern crate lazy_static;
......@@ -26,7 +28,7 @@ macro_rules! impl_mu_entity {
#[inline(always)]
fn id(&self) -> MuID {self.hdr.id()}
#[inline(always)]
fn name(&self) -> Option<MuName> {self.hdr.name()}
fn name(&self) -> MuName {self.hdr.name()}
fn as_entity(&self) -> &MuEntity {
let ref_ty : &$entity = self;
ref_ty as &MuEntity
......
......@@ -2682,7 +2682,7 @@ pub fn emit_code(fv: &mut MuFunctionVersion, vm: &VM) {
let mut file_path = path::PathBuf::new();
file_path.push(&vm.vm_options.flag_aot_emit_dir);
file_path.push(func.name().unwrap().to_string() + ".s");
file_path.push(func.name().to_string() + ".s");
let mut file = match File::create(file_path.as_path()) {
Err(why) => panic!("couldn't create emission file {}: {}", file_path.to_str().unwrap(), why),
Ok(file) => file
......
......@@ -130,7 +130,7 @@ impl <'a> InstructionSelection {
self.process_dest(&ops, fallthrough_dest, f_content, f_context, vm);
self.process_dest(&ops, branch_dest, f_content, f_context, vm);
let branch_target = f_content.get_block(branch_dest.target).name().unwrap();
let branch_target = f_content.get_block(branch_dest.target).name();
let ref cond = ops[cond];
......@@ -189,7 +189,7 @@ impl <'a> InstructionSelection {
let fallthrough_temp_block = format!("{}_{}_branch_fallthrough", self.current_fv_id, node.id());
self.start_block(fallthrough_temp_block, &vec![]);
let fallthrough_target = f_content.get_block(fallthrough_dest.target).name().unwrap();
let fallthrough_target = f_content.get_block(fallthrough_dest.target).name();
self.backend.emit_b(fallthrough_target);
},
......@@ -3481,7 +3481,7 @@ impl <'a> InstructionSelection {
let potentially_excepting = {
if resumption.is_some() {
let target_id = resumption.unwrap().exn_dest.target;
Some(f_content.get_block(target_id).name().unwrap())
Some(f_content.get_block(target_id).name().unwrap)
} else {
None
}
......@@ -4395,7 +4395,7 @@ impl CompilerPass for InstructionSelection {
self.current_func_start = Some({
let funcs = vm.funcs().read().unwrap();
let func = funcs.get(&func_ver.func_id).unwrap().read().unwrap();
let start_loc = self.backend.start_code(func.name().unwrap(), entry_block.name().unwrap());
let start_loc = self.backend.start_code(func.name(), entry_block.name());
if vm.vm_options.flag_emit_debug_info {
self.backend.add_cfi_sections(".eh_frame, .debug_frame");
self.backend.add_cfi_startproc();
......@@ -4424,7 +4424,7 @@ impl CompilerPass for InstructionSelection {
let is_exception_block = f_content.exception_blocks.contains(&block_id);
let block = f_content.get_block(*block_id);
let block_label = block.name().unwrap();
let block_label = block.name();
self.current_block = Some(block_label.clone());
self.current_block_in_ir = Some(block_label.clone());
......@@ -4479,7 +4479,7 @@ impl CompilerPass for InstructionSelection {
let func_name = {
let funcs = vm.funcs().read().unwrap();
let func = funcs.get(&func.func_id).unwrap().read().unwrap();
func.name().unwrap()
func.name()
};
// have to do this before 'finish_code()'
......
......@@ -2449,7 +2449,7 @@ fn make_value_symbolic(label: MuName, global: bool, ty: &P<MuType>, vm: &VM) ->
hdr: MuEntityHeader::unnamed(vm.next_id()),
ty : ty.clone(),
v : Value_::Memory(MemoryLocation::Symbolic {
label: label,
label: mangle_name(label)),
is_global: global
})
})
......
......@@ -103,13 +103,7 @@ pub fn emit_mu_types(vm: &VM) {
#[allow(dead_code)]
fn emit_muir(func: &MuFunctionVersion, vm: &VM) {
let func_name = match func.name() {
Some(name) => name,
None => {
// use func name
vm.name_of(func.func_id)
}
};
let func_name = func.name();
// create emit directory
create_emit_directory(vm);
......@@ -149,13 +143,7 @@ fn emit_muir(func: &MuFunctionVersion, vm: &VM) {
}
fn emit_muir_dot(func: &MuFunctionVersion, vm: &VM) {
let func_name = match func.name() {
Some(name) => name,
None => {
// use func name
vm.name_of(func.func_id)
}
};
let func_name = func.name();
// create emit directory
create_emit_directory(vm);
......@@ -164,7 +152,7 @@ fn emit_muir_dot(func: &MuFunctionVersion, vm: &VM) {
{
let mut file_path = path::PathBuf::new();
file_path.push(&vm.vm_options.flag_aot_emit_dir);
file_path.push(func_name.clone() + "_orig.dot");
file_path.push(func_name.clone() + ".orig.dot");
let mut file = match File::create(file_path.as_path()) {
Err(why) => panic!("couldn't create muir dot {}: {}", file_path.to_str().unwrap(), why),
Ok(file) => file
......@@ -201,7 +189,7 @@ fn emit_muir_dot_inner(file: &mut File,
// every graph node (basic block)
for (id, block) in f_content.blocks.iter() {
let block_name = block.name().unwrap();
let block_name = block.name();
// BBid [label = "name
file.write_fmt(format_args!("BB{} [label = \"[{}]{} ", *id, *id, &block_name)).unwrap();
......@@ -327,17 +315,11 @@ fn emit_muir_dot_inner(file: &mut File,
}
fn emit_mc_dot(func: &MuFunctionVersion, vm: &VM) {
let func_name = match func.name() {
Some(name) => name,
None => {
// use func name
vm.name_of(func.func_id)
}
};
let func_name = func.name();
// create emit directory/file
create_emit_directory(vm);
let mut file = create_emit_file(func_name.clone() + "_mc.dot", &vm);
let mut file = create_emit_file(func_name.clone() + ".mc.dot", &vm);
// diagraph func {
file.write_fmt(format_args!("digraph {} {{\n", func_name)).unwrap();
......@@ -388,7 +370,7 @@ fn emit_mc_dot(func: &MuFunctionVersion, vm: &VM) {
file.write_fmt(format_args!("{} -> {};\n", source_id, target_id)).unwrap();
}
None => {
panic!("cannot find block for inst {}", succ);
panic!("cannot find succesor {} for block {}", succ, block_name);
}
}
}
......
......@@ -417,3 +417,7 @@ impl RegGroup {
RegGroup::get_from_ty(&val.ty)
}
}
fn make_block_name<T: MuEntity>(header: &T, label: &str) -> MuName {
format!("{}:{}", header.name(), label)
}
\ No newline at end of file
......@@ -32,6 +32,7 @@ impl GenMovPhi {
struct IntermediateBlockInfo {
blk_id: MuID,
blk_name: MuName,
target: MuID,
from_args : Vec<P<TreeNode>>
}
......@@ -72,11 +73,11 @@ impl CompilerPass for GenMovPhi {
match last_inst.v {
TreeNode_::Instruction(inst) => {
let ref ops = inst.ops;
let inst_name = inst.name().clone();
match inst.v {
Instruction_::Branch2{cond, true_dest, false_dest, true_prob} => {
let true_dest = process_dest(true_dest, &mut new_blocks_to_insert, &ops, vm);
let false_dest = process_dest(false_dest, &mut new_blocks_to_insert, &ops, vm);
let true_dest = process_dest(true_dest, &mut new_blocks_to_insert, &ops, vm, &inst_name, "true");
let false_dest = process_dest(false_dest, &mut new_blocks_to_insert, &ops, vm, &inst_name, "false");
let new_inst = func.new_inst(Instruction{
hdr: inst.hdr.clone(),
......@@ -94,8 +95,8 @@ impl CompilerPass for GenMovPhi {
new_body.push(new_inst);
}
Instruction_::Call{data, resume} => {
let norm_dest = process_dest(resume.normal_dest, &mut new_blocks_to_insert, &ops, vm);
let exn_dest = process_dest(resume.exn_dest, &mut new_blocks_to_insert, &ops, vm);
let norm_dest = process_dest(resume.normal_dest, &mut new_blocks_to_insert, &ops, vm, &inst_name, "norm");
let exn_dest = process_dest(resume.exn_dest, &mut new_blocks_to_insert, &ops, vm, &inst_name, "exc");
let new_inst = func.new_inst(Instruction{
hdr: inst.hdr.clone(),
......@@ -114,8 +115,8 @@ impl CompilerPass for GenMovPhi {
new_body.push(new_inst);
}
Instruction_::CCall{data, resume} => {
let norm_dest = process_dest(resume.normal_dest, &mut new_blocks_to_insert, &ops, vm);
let exn_dest = process_dest(resume.exn_dest, &mut new_blocks_to_insert, &ops, vm);
let norm_dest = process_dest(resume.normal_dest, &mut new_blocks_to_insert, &ops, vm, &inst_name, "norm");
let exn_dest = process_dest(resume.exn_dest, &mut new_blocks_to_insert, &ops, vm, &inst_name, "exc");
let new_inst = func.new_inst(Instruction{
hdr: inst.hdr.clone(),
......@@ -134,10 +135,10 @@ impl CompilerPass for GenMovPhi {
new_body.push(new_inst);
},
Instruction_::Switch{cond, default, mut branches} => {
let default_dest = process_dest(default, &mut new_blocks_to_insert, &ops, vm);
let default_dest = process_dest(default, &mut new_blocks_to_insert, &ops, vm, &inst_name, "default");
let new_branches = branches.drain(..).map(|pair| {
let dest = process_dest(pair.1, &mut new_blocks_to_insert, &ops, vm);
let dest = process_dest(pair.1, &mut new_blocks_to_insert, &ops, vm, &inst_name, format!("case_{}", pair.0).as_str());
(pair.0, dest)
}).collect();
......@@ -192,9 +193,7 @@ impl CompilerPass for GenMovPhi {
for block_info in new_blocks_to_insert {
let block = {
let target_id = block_info.target;
let name = format!("intermediate_block_{}_to_{}", block_info.blk_id, target_id);
let mut ret = Block::new(MuEntityHeader::named(block_info.blk_id, name));
let mut ret = Block::new(MuEntityHeader::named(block_info.blk_id, block_info.blk_name.clone()));
vm.set_name(ret.as_entity());
......@@ -257,7 +256,7 @@ impl CompilerPass for GenMovPhi {
}
}
fn process_dest(dest: Destination, blocks_to_insert: &mut Vec<IntermediateBlockInfo>, ops: &Vec<P<TreeNode>>, vm: &VM) -> Destination {
fn process_dest(dest: Destination, blocks_to_insert: &mut Vec<IntermediateBlockInfo>, ops: &Vec<P<TreeNode>>, vm: &VM, inst: &MuName, label: &str) -> Destination {
if dest.args.is_empty() {
dest
} else {
......@@ -282,6 +281,7 @@ fn process_dest(dest: Destination, blocks_to_insert: &mut Vec<IntermediateBlockI
blocks_to_insert.push(IntermediateBlockInfo {
blk_id: new_blk_id,
blk_name: format!("{}:intermediate.{}", inst, label),
target: target,
from_args: from_args
});
......
......@@ -187,7 +187,7 @@ impl Inlining {
// finish current block
new_blocks.push(cur_block.clone());
let old_name = cur_block.name().unwrap();
let old_name = cur_block.name();
// start a new block
let new_name = format!("{}_cont_after_inline_{}", old_name, inst_id);
......@@ -334,7 +334,7 @@ fn copy_inline_blocks(caller: &mut Vec<Block>, ret_block: MuID, callee: &Functio
let old_id = block.id();
let new_id = *block_map.get(&block.id()).unwrap();
let mut block = Block {
hdr: MuEntityHeader::named(new_id, format!("inlinedblock{}_for_{}", new_id, block.name().unwrap())),
hdr: MuEntityHeader::named(new_id, format!("{}:inlinedblock.#{}", new_id, block.name())),
content: block.content.clone(),
control_flow: ControlFlow::default()
};
......
......@@ -143,7 +143,7 @@ impl CompilerPass for TreeGen {
debug!("check depth tree for {}", func);
for entry in func.content.as_ref().unwrap().blocks.iter() {
debug!("block {}", entry.1.name().unwrap());
debug!("block {}", entry.1.name());
for inst in entry.1.content.as_ref().unwrap().body.iter() {
debug!("{}", inst);
......
......@@ -108,7 +108,7 @@ pub extern fn throw_exception_internal(exception_obj: Address, frame_cursor: Add
set_previous_frame_pointer(frame_cursor, previous_frame_pointer);
}
}
// The abov eloop will only except when a catch block is found, so restore to it
// The above loop will only except when a catch block is found, so restore to it
unsafe { thread::exception_restore(catch_address, frame_cursor.to_ptr(), sp); }
}
......
......@@ -16,7 +16,8 @@
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <time.h>
#include <assert.h>
extern void* vm;
extern void* RODAL_END;
extern void mu_main(void*, void*, int, char**);
......
......@@ -59,11 +59,10 @@ pub fn get_function_info(function_addr: Address) -> (CName, Address) {
}
pub fn resolve_symbol(symbol: String) -> Address {
use std::ptr;
let c_symbol = CString::new(name_check(symbol.clone())).unwrap();
let c_symbol = CString::new(mangle_name(symbol.clone())).unwrap();
let rtld_default = unsafe {dlopen(ptr::null(), 0)};
let ret = unsafe {dlsym(rtld_default, c_symbol.as_ptr())};
......@@ -71,10 +70,7 @@ pub fn resolve_symbol(symbol: String) -> Address {
let error = unsafe {dlerror()};
if !error.is_null() {
let cstr = unsafe {CStr::from_ptr(error)};
error!("cannot find symbol: {}", symbol);
error!("{}", cstr.to_str().unwrap());
panic!("failed to resolve symbol");
panic!("failed to resolve symbol: {} ({})", symbol, cstr.to_str().unwrap());
}
Address::from_ptr(ret)
......@@ -153,6 +149,9 @@ pub extern fn mu_trace_level_log() {
VM::start_logging_trace();
}
#[no_mangle]
pub static mut LAST_TIME: c_ulong = 0;
#[no_mangle]
pub extern fn mu_main(edata: *const(), dumped_vm : *mut Arc<VM>, argc: c_int, argv: *const *const c_char) {
VM::start_logging_env();
......@@ -160,7 +159,7 @@ pub extern fn mu_main(edata: *const(), dumped_vm : *mut Arc<VM>, argc: c_int, ar
unsafe{rodal::load_asm_bounds(rodal::Address::from_ptr(dumped_vm), rodal::Address::from_ptr(edata))};
let vm = VM::resume_vm(dumped_vm);
let primordial = vm.primordial.read().unwrap();
if primordial.is_none() {
panic!("no primordial thread/stack/function. Client should provide an entry point");
......
......@@ -23,6 +23,7 @@
#include <stdio.h>
#include <dlfcn.h>
#include <pthread.h>
#include <time.h>
uint32_t mu_retval;
void muentry_set_retval(uint32_t x) {
......
......@@ -493,9 +493,7 @@ impl MuThread {
debug!("new sp: 0x{:x}", new_sp);
debug!("sp_store: 0x{:x}", sp_threadlocal_loc);
unsafe {
swap_to_mu_stack(new_sp, entry, sp_threadlocal_loc);
}
unsafe { swap_to_mu_stack(new_sp, entry, sp_threadlocal_loc); }
debug!("returned to Rust stack. Going to quit");
}) {
......
......@@ -41,7 +41,6 @@ fn link_executable_internal (files: Vec<PathBuf>, lib: &Vec<String>, libpath: &V
cc.arg("-lpthread");
}
// This needs to be at the bottom due to the linkage of librodall_alloc.a
for file in files {
info!("link with {:?}", file.as_path());
cc.arg(file.as_path());
......@@ -162,14 +161,6 @@ pub fn link_primordial (funcs: Vec<MuName>, out: &str, vm: &VM) -> PathBuf {
} else {
"target/release/libmu.a"
}));
/*// include rodal alloc static lib (it overrides free and realloc so it should be the last thing linked)
ret.push(get_path_under_mu(if cfg!(debug_assertions) {
"target/debug/deps/librodal_alloc.a"
} else {
"target/release/deps/librodal_alloc.a"
}));*/
ret
};
......
......@@ -30,15 +30,15 @@ pub struct MuIRBuilder {
/// by one thread, so there is no need for locking.
id_name_map: HashMap<MuID, MuName>,
/// The "trantient bundle" includes everything being built here.
bundle: TrantientBundle,
/// The "transient bundle" includes everything being built here.
bundle: TransientBundle,
}
pub type IdBMap<T> = HashMap<MuID, Box<T>>;
/// A trantient bundle, i.e. the bundle being built, but not yet loaded into the MuVM.
/// A transient bundle, i.e. the bundle being built, but not yet loaded into the MuVM.
#[derive(Default)]
pub struct TrantientBundle {
pub struct TransientBundle {
types: IdBMap<NodeType>,
sigs: IdBMap<NodeFuncSig>,
consts: IdBMap<NodeConst>,
......@@ -951,39 +951,113 @@ impl<'lb, 'lvm> BundleLoader<'lb, 'lvm> {
}
}
fn name_from_id(id: MuID, hint: &str) -> String {
format!("@uvm.unnamed.{}{}", hint, id)
}
fn ensure_name(&mut self, id: MuID, hint: &str) {
fn ensure_name(&mut self, id: MuID, parent_id: Option<MuID>) {
let prefix = match parent_id {
Some(parent_id) => self.get_name(parent_id) + ".",
None => "".to_string()
};
self.id_name_map.entry(id).or_insert_with(|| {
let name = BundleLoader::name_from_id(id, hint);
let name = format!("{}#{}", prefix, id);
trace!("Making name for ID {} : {}", id, name);
name
});
}
fn ensure_names(&mut self) {
// Make sure structs and hybrids have names because names are used to resolve cyclic
// dependencies.
// Make names for all unnamed entities that have parents, to be relative to their parents name (this is not strictly neccesary, but will make reading stuff the compiler generates easier)
// Give each struct and hybrid type a name (this is needed when structs/hybrids refer to themselves)
for (id, ty) in &self.b.bundle.types {
match **ty {
NodeType::TypeStruct { id: _, fieldtys: _ } => {
self.ensure_name(*id, "struct");
},
NodeType::TypeHybrid { id: _, fixedtys: _, varty: _ } => {
self.ensure_name(*id, "struct");
},
NodeType::TypeHybrid{..} | NodeType::TypeStruct{..} => self.ensure_name(*id, None),
_ => {}
}
}
for id in self.b.bundle.funcvers.keys() {
self.ensure_name(*id, "funcver");
// A func can be a parent of a function version, so make sure each one has a name
for id in self.b.bundle.funcs.keys() {
self.ensure_name(*id, None);
}
// Make each unnamed function version have a name relative to its function
for (fv_id, fv) in &self.b.bundle.funcvers {
self.ensure_name(*fv_id, Some(fv.func));
// Make each unnamed basic block have a name relative to it's enclosing function version
for bb_id in &fv.bbs {
self.ensure_name(*bb_id, Some(*fv_id));
}
}
for id in self.b.bundle.bbs.keys() {
self.ensure_name(*id, "funcver");
for (bb_id, bb) in &self.b.bundle.bbs {
// Make each of the basic blocks unnamed paremters have names relative to the block itself
for nor_id in &bb.nor_param_ids {
self.ensure_name(*nor_id, Some(*bb_id));
}
if bb.exc_param_id.is_some() {
self.ensure_name(bb.exc_param_id.unwrap(), Some(*bb_id));
}
// Make each of the blocks unnamed instructions have names relative to the block itself
for inst_id in &bb.insts {
self.ensure_name(*inst_id, Some(*bb_id));
// Make each unnamed instruction result have a name relative to the basic block
match self.b.bundle.insts.get(&inst_id) {
Some(inst) => {
match **inst {
// Instructions with a single result
NodeInst::NodeCmp{ref result_id, ..} |
NodeInst::NodeConv{ref result_id, ..} |