|
| 1 | +use std::collections::BTreeMap; |
| 2 | +use std::sync::Arc; |
| 3 | + |
| 4 | +use cranelift_codegen::control::ControlPlane; |
| 5 | +use cranelift_codegen::entity::SecondaryMap; |
| 6 | +use cranelift_codegen::ir::{Signature, UserExternalName}; |
| 7 | +use cranelift_codegen::isa::TargetIsa; |
| 8 | +use cranelift_module::{ |
| 9 | + DataId, ModuleDeclarations, ModuleError, ModuleReloc, ModuleRelocTarget, ModuleResult, |
| 10 | +}; |
| 11 | + |
| 12 | +use crate::prelude::*; |
| 13 | + |
| 14 | +pub(super) struct SerializableModule { |
| 15 | + isa: Arc<dyn TargetIsa>, |
| 16 | + inner: SerializableModuleInner, |
| 17 | +} |
| 18 | + |
| 19 | +#[derive(Debug, serde::Serialize, serde::Deserialize)] |
| 20 | +struct SerializableModuleInner { |
| 21 | + declarations: ModuleDeclarations, |
| 22 | + functions: BTreeMap<FuncId, Function>, |
| 23 | + data_objects: BTreeMap<DataId, DataDescription>, |
| 24 | +} |
| 25 | + |
| 26 | +impl SerializableModule { |
| 27 | + pub(crate) fn new(isa: Arc<dyn TargetIsa>) -> Self { |
| 28 | + SerializableModule { |
| 29 | + isa, |
| 30 | + inner: SerializableModuleInner { |
| 31 | + declarations: ModuleDeclarations::default(), |
| 32 | + functions: BTreeMap::new(), |
| 33 | + data_objects: BTreeMap::new(), |
| 34 | + }, |
| 35 | + } |
| 36 | + } |
| 37 | + |
| 38 | + pub(crate) fn serialize(self) -> Vec<u8> { |
| 39 | + postcard::to_stdvec(&self.inner).unwrap() |
| 40 | + } |
| 41 | + |
| 42 | + pub(crate) fn deserialize(blob: &[u8], isa: Arc<dyn TargetIsa>) -> SerializableModule { |
| 43 | + // FIXME check isa compatibility |
| 44 | + SerializableModule { isa, inner: postcard::from_bytes(blob).unwrap() } |
| 45 | + } |
| 46 | + |
| 47 | + pub(crate) fn apply_to(self, module: &mut dyn Module) { |
| 48 | + let mut function_map: SecondaryMap<FuncId, Option<FuncId>> = SecondaryMap::new(); |
| 49 | + let mut data_object_map: SecondaryMap<DataId, Option<DataId>> = SecondaryMap::new(); |
| 50 | + |
| 51 | + let mut remap_func_id = |
| 52 | + |module: &mut dyn Module, declarations: &ModuleDeclarations, func_id: FuncId| { |
| 53 | + if function_map[func_id].is_none() { |
| 54 | + let decl = declarations.get_function_decl(func_id); |
| 55 | + function_map[func_id] = Some(if let Some(name) = &decl.name { |
| 56 | + module.declare_function(name, decl.linkage, &decl.signature).unwrap() |
| 57 | + } else { |
| 58 | + module.declare_anonymous_function(&decl.signature).unwrap() |
| 59 | + }); |
| 60 | + } |
| 61 | + function_map[func_id].unwrap() |
| 62 | + }; |
| 63 | + |
| 64 | + let mut remap_data_id = |
| 65 | + |module: &mut dyn Module, declarations: &ModuleDeclarations, data_id: DataId| { |
| 66 | + if data_object_map[data_id].is_none() { |
| 67 | + let decl = declarations.get_data_decl(data_id); |
| 68 | + data_object_map[data_id] = Some(if let Some(name) = &decl.name { |
| 69 | + module.declare_data(name, decl.linkage, decl.writable, decl.tls).unwrap() |
| 70 | + } else { |
| 71 | + module.declare_anonymous_data(decl.writable, decl.tls).unwrap() |
| 72 | + }); |
| 73 | + } |
| 74 | + data_object_map[data_id].unwrap() |
| 75 | + }; |
| 76 | + |
| 77 | + for (func_id, mut func) in self.inner.functions { |
| 78 | + let func_id = remap_func_id(module, &self.inner.declarations, func_id); |
| 79 | + let user_named_funcs = func.params.user_named_funcs().clone(); |
| 80 | + for (ext_name_ref, ext_name) in user_named_funcs { |
| 81 | + if ext_name.namespace == 0 { |
| 82 | + func.params.reset_user_func_name( |
| 83 | + ext_name_ref, |
| 84 | + UserExternalName::new( |
| 85 | + 0, |
| 86 | + remap_func_id( |
| 87 | + module, |
| 88 | + &self.inner.declarations, |
| 89 | + FuncId::from_u32(ext_name.index), |
| 90 | + ) |
| 91 | + .as_u32(), |
| 92 | + ), |
| 93 | + ); |
| 94 | + } else if ext_name.namespace == 1 { |
| 95 | + func.params.reset_user_func_name( |
| 96 | + ext_name_ref, |
| 97 | + UserExternalName::new( |
| 98 | + 1, |
| 99 | + remap_data_id( |
| 100 | + module, |
| 101 | + &self.inner.declarations, |
| 102 | + DataId::from_u32(ext_name.index), |
| 103 | + ) |
| 104 | + .as_u32(), |
| 105 | + ), |
| 106 | + ); |
| 107 | + } else { |
| 108 | + unreachable!(); |
| 109 | + } |
| 110 | + } |
| 111 | + module.define_function(func_id, &mut Context::for_function(func)).unwrap(); |
| 112 | + } |
| 113 | + |
| 114 | + for (data_id, mut data) in self.inner.data_objects { |
| 115 | + let data_id = remap_data_id(module, &self.inner.declarations, data_id); |
| 116 | + for ext_name in data |
| 117 | + .function_decls |
| 118 | + .iter_mut() |
| 119 | + .map(|(_, ext_name)| ext_name) |
| 120 | + .chain(data.data_decls.iter_mut().map(|(_, ext_name)| ext_name)) |
| 121 | + { |
| 122 | + match *ext_name { |
| 123 | + ModuleRelocTarget::User { namespace, ref mut index } => { |
| 124 | + if namespace == 0 { |
| 125 | + *index = remap_func_id( |
| 126 | + module, |
| 127 | + &self.inner.declarations, |
| 128 | + FuncId::from_u32(*index), |
| 129 | + ) |
| 130 | + .as_u32(); |
| 131 | + } else if namespace == 1 { |
| 132 | + *index = remap_data_id( |
| 133 | + module, |
| 134 | + &self.inner.declarations, |
| 135 | + DataId::from_u32(*index), |
| 136 | + ) |
| 137 | + .as_u32(); |
| 138 | + } else { |
| 139 | + unreachable!(); |
| 140 | + } |
| 141 | + } |
| 142 | + ModuleRelocTarget::KnownSymbol(_) |
| 143 | + | ModuleRelocTarget::LibCall(_) |
| 144 | + | ModuleRelocTarget::FunctionOffset(_, _) => {} |
| 145 | + } |
| 146 | + } |
| 147 | + module.define_data(data_id, &data).unwrap(); |
| 148 | + } |
| 149 | + |
| 150 | + //todo!(); |
| 151 | + } |
| 152 | +} |
| 153 | + |
| 154 | +impl Module for SerializableModule { |
| 155 | + fn isa(&self) -> &dyn TargetIsa { |
| 156 | + &*self.isa |
| 157 | + } |
| 158 | + |
| 159 | + fn declarations(&self) -> &ModuleDeclarations { |
| 160 | + &self.inner.declarations |
| 161 | + } |
| 162 | + |
| 163 | + fn declare_function( |
| 164 | + &mut self, |
| 165 | + name: &str, |
| 166 | + linkage: Linkage, |
| 167 | + signature: &Signature, |
| 168 | + ) -> ModuleResult<FuncId> { |
| 169 | + let (id, _linkage) = self.inner.declarations.declare_function(name, linkage, signature)?; |
| 170 | + |
| 171 | + Ok(id) |
| 172 | + } |
| 173 | + |
| 174 | + fn declare_anonymous_function(&mut self, signature: &Signature) -> ModuleResult<FuncId> { |
| 175 | + Ok(self.inner.declarations.declare_anonymous_function(signature)?) |
| 176 | + } |
| 177 | + |
| 178 | + fn declare_data( |
| 179 | + &mut self, |
| 180 | + name: &str, |
| 181 | + linkage: Linkage, |
| 182 | + writable: bool, |
| 183 | + tls: bool, |
| 184 | + ) -> ModuleResult<DataId> { |
| 185 | + let (id, _linkage) = self.inner.declarations.declare_data(name, linkage, writable, tls)?; |
| 186 | + |
| 187 | + Ok(id) |
| 188 | + } |
| 189 | + |
| 190 | + fn declare_anonymous_data(&mut self, writable: bool, tls: bool) -> ModuleResult<DataId> { |
| 191 | + Ok(self.inner.declarations.declare_anonymous_data(writable, tls)?) |
| 192 | + } |
| 193 | + |
| 194 | + fn define_function_with_control_plane( |
| 195 | + &mut self, |
| 196 | + func_id: FuncId, |
| 197 | + ctx: &mut Context, |
| 198 | + ctrl_plane: &mut ControlPlane, |
| 199 | + ) -> ModuleResult<()> { |
| 200 | + let decl = self.inner.declarations.get_function_decl(func_id); |
| 201 | + if !decl.linkage.is_definable() { |
| 202 | + return Err(ModuleError::InvalidImportDefinition( |
| 203 | + decl.name.as_deref().unwrap_or("<anonymous>").to_owned(), |
| 204 | + )); |
| 205 | + } |
| 206 | + |
| 207 | + if self.inner.functions.get(&func_id).is_some() { |
| 208 | + return Err(ModuleError::DuplicateDefinition( |
| 209 | + decl.name.as_deref().unwrap_or("<anonymous>").to_owned(), |
| 210 | + )); |
| 211 | + } |
| 212 | + |
| 213 | + ctx.verify_if(&*self.isa)?; |
| 214 | + ctx.optimize(&*self.isa, ctrl_plane)?; |
| 215 | + |
| 216 | + self.inner.functions.insert(func_id, ctx.func.clone()); |
| 217 | + |
| 218 | + Ok(()) |
| 219 | + } |
| 220 | + |
| 221 | + fn define_function_bytes( |
| 222 | + &mut self, |
| 223 | + _func_id: FuncId, |
| 224 | + _alignment: u64, |
| 225 | + _bytes: &[u8], |
| 226 | + _relocs: &[ModuleReloc], |
| 227 | + ) -> ModuleResult<()> { |
| 228 | + unimplemented!() |
| 229 | + } |
| 230 | + |
| 231 | + fn define_data(&mut self, data_id: DataId, data: &DataDescription) -> ModuleResult<()> { |
| 232 | + let decl = self.inner.declarations.get_data_decl(data_id); |
| 233 | + if !decl.linkage.is_definable() { |
| 234 | + return Err(ModuleError::InvalidImportDefinition( |
| 235 | + decl.name.as_deref().unwrap_or("<anonymous>").to_owned(), |
| 236 | + )); |
| 237 | + } |
| 238 | + |
| 239 | + if self.inner.data_objects.get(&data_id).is_some() { |
| 240 | + return Err(ModuleError::DuplicateDefinition( |
| 241 | + decl.name.as_deref().unwrap_or("<anonymous>").to_owned(), |
| 242 | + )); |
| 243 | + } |
| 244 | + |
| 245 | + self.inner.data_objects.insert(data_id, data.clone()); |
| 246 | + |
| 247 | + Ok(()) |
| 248 | + } |
| 249 | +} |
0 commit comments