fugue_ir/
space_manager.rs1use std::fmt::Debug;
2use std::sync::Arc;
3
4use crate::address::AddressValue;
5use crate::deserialise::Error;
6use crate::disassembly::IRBuilderArena;
7use crate::space::{AddressSpace, AddressSpaceId, Space, SpaceKind, SpaceProperty};
8
9#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
10pub struct SpaceManager {
11 spaces: Vec<Arc<AddressSpace>>,
12 constant_space: usize,
13 default_space: usize,
14 register_space: usize,
15 unique_space: usize,
16}
17
18pub trait FromSpace<'z, T> {
19 fn from_space(t: T, manager: &SpaceManager) -> Self;
20 fn from_space_with(t: T, arena: &'z IRBuilderArena, manager: &SpaceManager) -> Self;
21}
22
23pub trait IntoSpace<'z, T> {
24 fn into_space(self, manager: &SpaceManager) -> T;
25 fn into_space_with(self, arena: &'z IRBuilderArena, manager: &SpaceManager) -> T;
26}
27
28impl<'z, T, U> IntoSpace<'z, T> for U
29where
30 T: FromSpace<'z, U>,
31{
32 fn into_space(self, manager: &SpaceManager) -> T {
33 T::from_space(self, manager)
34 }
35
36 fn into_space_with(self, arena: &'z IRBuilderArena, manager: &SpaceManager) -> T {
37 T::from_space_with(self, arena, manager)
38 }
39}
40
41impl SpaceManager {
42 pub fn address_from<S: AsRef<str>>(&self, space: S, offset: u64) -> Option<AddressValue> {
43 let space = self.space_by_name(space)?;
44 Some(AddressValue::new(space, offset))
45 }
46
47 pub fn address_size(&self) -> usize {
48 unsafe { self.spaces.get_unchecked(self.default_space) }.address_size()
49 }
50
51 pub fn spaces(&self) -> &[Arc<AddressSpace>] {
52 self.spaces.as_ref()
53 }
54
55 pub fn space_by_name<S: AsRef<str>>(&self, name: S) -> Option<Arc<AddressSpace>> {
56 let name = name.as_ref();
57 self.spaces.iter().find_map(|space| {
58 if space.name() == name {
59 Some(space.clone())
60 } else {
61 None
62 }
63 })
64 }
65
66 pub fn space_by_id(&self, id: AddressSpaceId) -> &AddressSpace {
67 &self.spaces[id.index()]
68 }
69
70 pub unsafe fn unchecked_space_by_id(&self, id: AddressSpaceId) -> &AddressSpace {
71 &*self.spaces.get_unchecked(id.index())
72 }
73
74 pub fn constant_space(&self) -> Arc<AddressSpace> {
75 unsafe { self.spaces.get_unchecked(self.constant_space) }.clone()
76 }
77
78 pub fn constant_space_ref(&self) -> &AddressSpace {
79 &*unsafe { self.spaces.get_unchecked(self.constant_space) }
80 }
81
82 pub fn constant_space_id(&self) -> AddressSpaceId {
83 AddressSpaceId::constant_id(self.constant_space)
84 }
85
86 pub fn default_space(&self) -> Arc<AddressSpace> {
87 unsafe { self.spaces.get_unchecked(self.default_space) }.clone()
88 }
89
90 pub fn default_space_ref(&self) -> &AddressSpace {
91 &*unsafe { self.spaces.get_unchecked(self.default_space) }
92 }
93
94 pub fn default_space_id(&self) -> AddressSpaceId {
95 AddressSpaceId::default_id(self.default_space)
96 }
97
98 pub fn register_space(&self) -> Arc<AddressSpace> {
99 unsafe { self.spaces.get_unchecked(self.register_space) }.clone()
100 }
101
102 pub fn register_space_ref(&self) -> &AddressSpace {
103 &*unsafe { self.spaces.get_unchecked(self.register_space) }
104 }
105
106 pub fn register_space_id(&self) -> AddressSpaceId {
107 AddressSpaceId::register_id(self.register_space)
108 }
109
110 pub fn unique_space(&self) -> Arc<AddressSpace> {
111 unsafe { self.spaces.get_unchecked(self.unique_space) }.clone()
112 }
113
114 pub fn unique_space_ref(&self) -> &AddressSpace {
115 &*unsafe { self.spaces.get_unchecked(self.unique_space) }
116 }
117
118 pub fn unique_space_id(&self) -> AddressSpaceId {
119 AddressSpaceId::unique_id(self.unique_space)
120 }
121
122 pub fn add_space<S: AsRef<str>>(
123 &mut self,
124 kind: SpaceKind,
125 name: S,
126 address_size: usize,
127 word_size: usize,
128 properties: Option<SpaceProperty>,
129 delay: usize,
130 ) -> Arc<AddressSpace> {
131 let index = self.spaces.len();
132 let space = Arc::new(AddressSpace::Space(Space::new(
133 kind,
134 name,
135 address_size,
136 word_size,
137 index,
138 properties,
139 delay,
140 )));
141 self.spaces.push(space.clone());
142 space
143 }
144
145 pub fn add_space_like<S: AsRef<str>>(
146 &mut self,
147 name: S,
148 space: &AddressSpace,
149 ) -> Arc<AddressSpace> {
150 self.add_space(
151 space.kind(),
152 name,
153 space.address_size(),
154 space.word_size(),
155 Some(space.properties()),
156 space.delay(),
157 )
158 }
159
160 pub fn from_xml(input: xml::Node) -> Result<Self, Error> {
161 if input.tag_name().name() != "spaces" {
162 return Err(Error::TagUnexpected(input.tag_name().name().to_owned()));
163 }
164
165 let mut spaces = vec![Arc::new(AddressSpace::constant("const", 0))];
166 let mut default_space = 0;
167 let mut register_space = 0;
168 let mut unique_space = 0;
169
170 let default_name = input
171 .attribute("defaultspace")
172 .ok_or_else(|| Error::AttributeExpected("defaultspace"))?;
173
174 for (index, child) in input
175 .children()
176 .filter(xml::Node::is_element)
177 .enumerate()
178 .map(|(i, c)| (i + 1, c))
179 {
180 let mut space = AddressSpace::from_xml(child)?;
181
182 if space.index() != index {
183 return Err(Error::Invariant("space index mismatch"));
184 }
185
186 if space.name() == default_name {
187 default_space = index;
188 space.kind = SpaceKind::Default;
189 }
190
191 if space.name() == "register" {
192 register_space = index;
193 space.kind = SpaceKind::Register;
194 }
195
196 if space.name() == "unique" {
197 unique_space = index;
198 }
199
200 spaces.push(Arc::new(space));
201 }
202
203 if default_space == 0 {
204 return Err(Error::Invariant("non-constant default space not defined"));
205 }
206
207 if register_space == 0 {
208 return Err(Error::Invariant("register space not defined"));
209 }
210
211 if unique_space == 0 {
212 return Err(Error::Invariant("unique space not defined"));
213 }
214
215 Ok(Self {
216 spaces,
217 constant_space: 0,
218 default_space,
219 register_space,
220 unique_space,
221 })
222 }
223}