Commit a5930291 authored by Kunshan Wang's avatar Kunshan Wang

IRBuilder: Actually add things into VM

Also fixed a bug in FuncVer building.
parent e56e09ef
...@@ -17,23 +17,23 @@ pub struct MuIRBuilder { ...@@ -17,23 +17,23 @@ pub struct MuIRBuilder {
bundle: TrantientBundle, bundle: TrantientBundle,
} }
pub type IdMap<T> = HashMap<MuID, Box<T>>; 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 trantient bundle, i.e. the bundle being built, but not yet loaded into the MuVM.
#[derive(Default)] #[derive(Default)]
pub struct TrantientBundle { pub struct TrantientBundle {
types: IdMap<NodeType>, types: IdBMap<NodeType>,
sigs: IdMap<NodeFuncSig>, sigs: IdBMap<NodeFuncSig>,
consts: IdMap<NodeConst>, consts: IdBMap<NodeConst>,
globals: IdMap<NodeGlobalCell>, globals: IdBMap<NodeGlobalCell>,
funcs: IdMap<NodeFunc>, funcs: IdBMap<NodeFunc>,
expfuncs: IdMap<NodeExpFunc>, expfuncs: IdBMap<NodeExpFunc>,
funcvers: IdMap<NodeFuncVer>, funcvers: IdBMap<NodeFuncVer>,
bbs: IdMap<NodeBB>, bbs: IdBMap<NodeBB>,
insts: IdMap<NodeInst>, insts: IdBMap<NodeInst>,
dest_clauses: IdMap<NodeDestClause>, dest_clauses: IdBMap<NodeDestClause>,
exc_clauses: IdMap<NodeExcClause>, exc_clauses: IdBMap<NodeExcClause>,
ka_clauses: IdMap<NodeKeepaliveClause>, ka_clauses: IdBMap<NodeKeepaliveClause>,
} }
impl MuIRBuilder { impl MuIRBuilder {
...@@ -527,9 +527,10 @@ struct BundleLoader<'lb, 'lvm> { ...@@ -527,9 +527,10 @@ struct BundleLoader<'lb, 'lvm> {
visited: HashSet<MuID>, visited: HashSet<MuID>,
built_types: IdPMap<MuType>, built_types: IdPMap<MuType>,
built_sigs: IdPMap<MuFuncSig>, built_sigs: IdPMap<MuFuncSig>,
built_values: IdPMap<Value>, built_constants: IdPMap<Value>,
built_funcs: IdPMap<MuFunction>, built_globals: IdPMap<Value>,
built_funcvers: IdPMap<MuFunctionVersion>, built_funcs: IdBMap<MuFunction>,
built_funcvers: IdBMap<MuFunctionVersion>,
struct_id_tags: Vec<(MuID, MuName)>, struct_id_tags: Vec<(MuID, MuName)>,
built_refi64: Option<P<MuType>>, built_refi64: Option<P<MuType>>,
built_i1: Option<P<MuType>>, built_i1: Option<P<MuType>>,
...@@ -548,7 +549,8 @@ fn load_bundle(b: &mut MuIRBuilder) { ...@@ -548,7 +549,8 @@ fn load_bundle(b: &mut MuIRBuilder) {
visited: Default::default(), visited: Default::default(),
built_types: Default::default(), built_types: Default::default(),
built_sigs: Default::default(), built_sigs: Default::default(),
built_values: Default::default(), built_constants: Default::default(),
built_globals: Default::default(),
built_funcs: Default::default(), built_funcs: Default::default(),
built_funcvers: Default::default(), built_funcvers: Default::default(),
struct_id_tags: Default::default(), struct_id_tags: Default::default(),
...@@ -572,6 +574,7 @@ impl<'lb, 'lvm> BundleLoader<'lb, 'lvm> { ...@@ -572,6 +574,7 @@ impl<'lb, 'lvm> BundleLoader<'lb, 'lvm> {
fn load_bundle(&mut self) { fn load_bundle(&mut self) {
self.ensure_names(); self.ensure_names();
self.build_toplevels(); self.build_toplevels();
self.add_everything_to_vm();
} }
fn ensure_refi64(&mut self) -> P<MuType> { fn ensure_refi64(&mut self) -> P<MuType> {
...@@ -880,7 +883,7 @@ impl<'lb, 'lvm> BundleLoader<'lb, 'lvm> { ...@@ -880,7 +883,7 @@ impl<'lb, 'lvm> BundleLoader<'lb, 'lvm> {
trace!("Constant built: {} {:?}", id, impl_val); trace!("Constant built: {} {:?}", id, impl_val);
self.built_values.insert(id, P(impl_val)); self.built_constants.insert(id, P(impl_val));
} }
fn build_func(&mut self, id: MuID) { fn build_func(&mut self, id: MuID) {
...@@ -902,7 +905,7 @@ impl<'lb, 'lvm> BundleLoader<'lb, 'lvm> { ...@@ -902,7 +905,7 @@ impl<'lb, 'lvm> BundleLoader<'lb, 'lvm> {
trace!("Function built: {} {:?}", id, impl_fun); trace!("Function built: {} {:?}", id, impl_fun);
self.built_funcs.insert(id, P(impl_fun)); self.built_funcs.insert(id, Box::new(impl_fun));
let impl_ty = self.ensure_funcref(fun.sig); let impl_ty = self.ensure_funcref(fun.sig);
...@@ -914,19 +917,26 @@ impl<'lb, 'lvm> BundleLoader<'lb, 'lvm> { ...@@ -914,19 +917,26 @@ impl<'lb, 'lvm> BundleLoader<'lb, 'lvm> {
trace!("Function value built: {} {:?}", id, impl_val); trace!("Function value built: {} {:?}", id, impl_val);
self.built_values.insert(id, P(impl_val)); self.built_constants.insert(id, P(impl_val));
} }
fn get_sig_for_func(&mut self, id: MuID) -> P<MuFuncSig> {
if let Some(impl_func) = self.built_funcs.get(&id) {
impl_func.sig.clone()
} else {
self.vm.get_func_sig_for_func(id)
}
}
fn build_funcver(&mut self, id: MuID) { fn build_funcver(&mut self, id: MuID) {
let fv = self.b.bundle.funcvers.get(&id).unwrap(); let fv = self.b.bundle.funcvers.get(&id).unwrap();
trace!("Building function version {} {:?}", id, fv); trace!("Building function version {} {:?}", id, fv);
let hdr = self.make_mu_entity_header(id); let hdr = self.make_mu_entity_header(id);
let impl_sig = { let func_id = fv.func;
let fun = self.built_funcs.get(&fv.func).unwrap(); let impl_sig = self.get_sig_for_func(func_id);
fun.sig.clone()
};
let mut fcb: FuncCtxBuilder = Default::default(); let mut fcb: FuncCtxBuilder = Default::default();
...@@ -943,7 +953,7 @@ impl<'lb, 'lvm> BundleLoader<'lb, 'lvm> { ...@@ -943,7 +953,7 @@ impl<'lb, 'lvm> BundleLoader<'lb, 'lvm> {
let impl_fv = MuFunctionVersion { let impl_fv = MuFunctionVersion {
hdr: hdr, hdr: hdr,
func_id: id, func_id: func_id,
sig: impl_sig, sig: impl_sig,
content: Some(ctn), content: Some(ctn),
context: fcb.ctx, context: fcb.ctx,
...@@ -952,7 +962,7 @@ impl<'lb, 'lvm> BundleLoader<'lb, 'lvm> { ...@@ -952,7 +962,7 @@ impl<'lb, 'lvm> BundleLoader<'lb, 'lvm> {
trace!("Function version built {} {:?}", id, impl_fv); trace!("Function version built {} {:?}", id, impl_fv);
self.built_funcvers.insert(id, P(impl_fv)); self.built_funcvers.insert(id, Box::new(impl_fv));
} }
/// Copied from ast::ir::*. That was implemented for the previous API which implies mutability. /// Copied from ast::ir::*. That was implemented for the previous API which implies mutability.
...@@ -995,7 +1005,7 @@ impl<'lb, 'lvm> BundleLoader<'lb, 'lvm> { ...@@ -995,7 +1005,7 @@ impl<'lb, 'lvm> BundleLoader<'lb, 'lvm> {
fn get_treenode(&self, fcb: &FuncCtxBuilder, id: MuID) -> P<TreeNode> { fn get_treenode(&self, fcb: &FuncCtxBuilder, id: MuID) -> P<TreeNode> {
if let Some(tn) = fcb.tree_nodes.get(&id) { if let Some(tn) = fcb.tree_nodes.get(&id) {
tn.clone() tn.clone()
} else if let Some(v) = self.built_values.get(&id) { } else if let Some(v) = self.built_constants.get(&id) {
self.new_global(v.clone()) self.new_global(v.clone())
} else { } else {
panic!("Operand {} is neither a local var or a global var", id) panic!("Operand {} is neither a local var or a global var", id)
...@@ -1352,4 +1362,22 @@ impl<'lb, 'lvm> BundleLoader<'lb, 'lvm> { ...@@ -1352,4 +1362,22 @@ impl<'lb, 'lvm> BundleLoader<'lb, 'lvm> {
(impl_dest, var_treenodes) (impl_dest, var_treenodes)
} }
fn add_everything_to_vm(&mut self) {
let vm = self.vm;
trace!("Loading bundle to the VM...");
vm.declare_many(
&mut self.id_name_map,
&mut self.built_types,
&mut self.built_sigs,
&mut self.built_constants,
&mut self.built_globals,
&mut self.built_funcs,
&mut self.built_funcvers,
);
trace!("Bundle loaded to the VM!");
}
} }
...@@ -478,6 +478,15 @@ impl <'a> VM { ...@@ -478,6 +478,15 @@ impl <'a> VM {
funcs.insert(func.id(), RwLock::new(func)); funcs.insert(func.id(), RwLock::new(func));
} }
/// The IR builder needs to look-up the function signature from the existing function ID.
pub fn get_func_sig_for_func(&self, id: MuID) -> P<MuFuncSig> {
let funcs_lock = self.funcs.read().unwrap();
match funcs_lock.get(&id) {
Some(func) => func.read().unwrap().sig.clone(),
None => panic!("cannot find Mu function #{}", id)
}
}
pub fn define_func_version (&self, func_ver: MuFunctionVersion) { pub fn define_func_version (&self, func_ver: MuFunctionVersion) {
info!("define function version {}", func_ver); info!("define function version {}", func_ver);
// record this version // record this version
...@@ -501,6 +510,72 @@ impl <'a> VM { ...@@ -501,6 +510,72 @@ impl <'a> VM {
// redefinition happens here // redefinition happens here
// do stuff // do stuff
} }
/// Add a new bundle into VM.
///
/// This function will drain the contents of all arguments.
///
/// Ideally, this function should happen atomically. e.g. The client should not see a new type
/// added without also seeing a new function added.
pub fn declare_many(&self,
new_id_name_map: &mut HashMap<MuID, MuName>,
new_types: &mut HashMap<MuID, P<MuType>>,
new_func_sigs: &mut HashMap<MuID, P<MuFuncSig>>,
new_constants: &mut HashMap<MuID, P<Value>>,
new_globals: &mut HashMap<MuID, P<Value>>,
new_funcs: &mut HashMap<MuID, Box<MuFunction>>,
new_func_vers: &mut HashMap<MuID, Box<MuFunctionVersion>>
) {
// Make sure other components, if ever acquiring multiple locks at the same time, acquire
// them in this order, to prevent deadlock.
let mut id_name_map = self.id_name_map.write().unwrap();
let mut name_id_map = self.name_id_map.write().unwrap();
let mut types = self.types.write().unwrap();
let mut constants = self.constants.write().unwrap();
let mut globals = self.globals.write().unwrap();
let mut func_sigs = self.func_sigs.write().unwrap();
let mut funcs = self.funcs.write().unwrap();
let mut func_vers = self.func_vers.write().unwrap();
for (id, name) in new_id_name_map.drain() {
id_name_map.insert(id, name.clone());
name_id_map.insert(name, id);
}
for (id, obj) in new_types.drain() {
types.insert(id, obj);
}
for (id, obj) in new_constants.drain() {
constants.insert(id, obj);
}
for (id, obj) in new_globals.drain() {
globals.insert(id, obj);
}
for (id, obj) in new_func_sigs.drain() {
func_sigs.insert(id, obj);
}
for (id, obj) in new_funcs.drain() {
funcs.insert(id, RwLock::new(*obj));
}
for (id, obj) in new_func_vers.drain() {
let func_id = obj.func_id;
func_vers.insert(id, RwLock::new(*obj));
{
trace!("Adding funcver {} as a version of {}...", id, func_id);
let func = funcs.get_mut(&func_id).unwrap();
func.write().unwrap().new_version(id);
trace!("Added funcver {} as a version of {} {:?}.", id, func_id, func);
}
}
// Locks released here
}
pub fn add_compiled_func (&self, func: CompiledFunction) { pub fn add_compiled_func (&self, func: CompiledFunction) {
debug_assert!(self.funcs.read().unwrap().contains_key(&func.func_id)); debug_assert!(self.funcs.read().unwrap().contains_key(&func.func_id));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment