Skip to content

Commit 59a1d9e

Browse files
committed
Copy serializable_module.rs from the fake_lto branch
1 parent a6fc673 commit 59a1d9e

File tree

4 files changed

+258
-2
lines changed

4 files changed

+258
-2
lines changed

Cargo.lock

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ crate-type = ["dylib"]
88

99
[dependencies]
1010
# These have to be in sync with each other
11-
cranelift-codegen = { version = "0.122.0", default-features = false, features = ["std", "timing", "unwind", "all-native-arch", "incremental-cache"] }
11+
cranelift-codegen = { version = "0.122.0", default-features = false, features = ["std", "timing", "unwind", "all-native-arch", "enable-serde", "incremental-cache"] }
1212
cranelift-frontend = { version = "0.122.0" }
13-
cranelift-module = { version = "0.122.0" }
13+
cranelift-module = { version = "0.122.0", features = ["enable-serde"] }
1414
cranelift-native = { version = "0.122.0" }
1515
cranelift-jit = { version = "0.122.0", optional = true }
1616
cranelift-object = { version = "0.122.0" }
@@ -21,6 +21,8 @@ object = { version = "0.36", default-features = false, features = ["std", "read_
2121
indexmap = "2.0.0"
2222
libloading = { version = "0.8.0", optional = true }
2323
smallvec = "1.8.1"
24+
serde = { version = "1.0.203", features = ["derive"] }
25+
postcard = { version = "1.0.8", default-features = false, features = ["use-std"] }
2426

2527
[patch.crates-io]
2628
# Uncomment to use an unreleased version of cranelift

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ mod num;
8181
mod optimize;
8282
mod pointer;
8383
mod pretty_clif;
84+
mod serializable_module;
8485
mod toolchain;
8586
mod unsize;
8687
mod unwind_module;

src/serializable_module.rs

Lines changed: 249 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,249 @@
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

Comments
 (0)