1use crate::types::BasicTypeRef;
6use crate::types::{TypedRegister, VmType};
7use source_map_node::Node;
8use std::cmp::PartialOrd;
9use std::fmt::{Debug, Display, Formatter};
10use std::ops::{Add, Div, Sub};
11use swamp_vm_isa::prelude::align;
12use swamp_vm_isa::{
13 CountU32, FrameMemorySize, InstructionPosition, MemoryAlignment, MemoryOffset, MemorySize,
14};
15
16pub mod prelude;
17pub mod types;
18
19pub struct StackMemoryAddress(pub u32);
20
21impl Add<MemorySize> for StackMemoryAddress {
22 type Output = Self;
23
24 fn add(self, rhs: MemorySize) -> Self::Output {
25 Self(self.0 + rhs.0)
26 }
27}
28
29#[derive(Debug, Copy, Clone, PartialOrd, Ord, Eq, PartialEq)]
30pub struct HeapMemorySize(pub u32);
31
32impl Div<Self> for HeapMemorySize {
33 type Output = CountU32;
34
35 fn div(self, rhs: Self) -> Self::Output {
36 assert!(rhs.0 > 0, "Division by zero in MemorySize");
37 assert!(
38 self.0 > 0,
39 "Numerator must be positive in MemorySize division"
40 );
41 assert_eq!(
42 self.0 % rhs.0,
43 0,
44 "MemorySize division must be exact and positive"
45 );
46
47 CountU32(self.0 / rhs.0)
48 }
49}
50
51impl Add<MemoryOffset> for StackMemoryAddress {
52 type Output = Self;
53
54 fn add(self, rhs: MemoryOffset) -> Self::Output {
55 Self(self.0 + rhs.0)
56 }
57}
58
59#[derive(Debug, Copy, Clone)]
60pub struct CountU16(pub u16);
61
62impl Display for CountU16 {
63 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
64 write!(f, "{}", self.0)
65 }
66}
67
68impl FrameMemoryAddress {
69 #[must_use]
70 pub const fn advance(&self, memory_offset: MemoryOffset) -> Self {
71 Self(self.0 + memory_offset.0)
72 }
73}
74
75impl FrameMemoryAddress {
77 #[must_use]
78 pub const fn add(&self, memory_size: MemorySize) -> Self {
79 Self(self.0 + memory_size.0)
80 }
81
82 #[must_use]
83 pub const fn add_offset(&self, memory_offset: MemoryOffset) -> Self {
84 Self(self.0 + memory_offset.0)
85 }
86 #[must_use]
87 pub const fn as_size(&self) -> FrameMemorySize {
88 FrameMemorySize(self.0)
89 }
90}
91
92impl StackMemoryAddress {
93 #[must_use]
94 pub const fn add(&self, memory_size: MemorySize) -> Self {
95 Self(self.0 + memory_size.0)
96 }
97}
98
99#[derive(Debug, Copy, Clone, Eq, PartialEq)]
100pub struct FrameMemoryAddress(pub u32);
101
102impl Display for FrameMemoryAddress {
103 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
104 write!(f, "${:04X}", self.0)
105 }
106}
107
108impl Add<MemoryOffset> for FrameMemoryAddress {
109 type Output = Self;
110
111 fn add(self, rhs: MemoryOffset) -> Self::Output {
112 Self(self.0 + rhs.0)
113 }
114}
115
116#[derive(Debug, Copy, Clone)]
117pub struct FrameMemoryRegion {
118 pub addr: FrameMemoryAddress,
119 pub size: MemorySize,
120}
121
122impl Display for FrameMemoryRegion {
123 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
124 write!(f, "{}:{}", self.addr, self.size)
125 }
126}
127
128impl Default for FrameMemoryRegion {
129 fn default() -> Self {
130 Self {
131 addr: FrameMemoryAddress(0),
132 size: MemorySize(0),
133 }
134 }
135}
136
137impl FrameMemoryRegion {
138 #[must_use]
139 pub const fn new(frame_addr: FrameMemoryAddress, size: MemorySize) -> Self {
140 Self {
141 addr: frame_addr,
142 size,
143 }
144 }
145
146 #[must_use]
147 pub fn last_valid_end_addr(&self) -> FrameMemoryAddress {
148 self.addr.add(MemoryOffset(self.size.0))
149 }
150}
151
152impl FrameMemoryRegion {
153 #[must_use]
154 pub const fn addr(&self) -> FrameMemoryAddress {
155 self.addr
156 }
157}
158
159#[derive(Debug, Copy, Clone)]
160pub struct FrameMemoryAddressIndirectPointer(pub FrameMemoryAddress);
161
162#[derive(Debug, Copy, Clone)]
163pub struct TempFrameMemoryAddress(pub FrameMemoryAddress);
164
165impl TempFrameMemoryAddress {
166 #[must_use]
167 pub const fn to_addr(&self) -> FrameMemoryAddress {
168 self.0
169 }
170}
171
172#[must_use]
173pub fn align_to(addr: MemoryOffset, alignment: MemoryAlignment) -> MemoryOffset {
174 MemoryOffset(align(addr.0 as usize, alignment.into()) as u32)
175}
176
177#[must_use]
195pub fn adjust_size_to_alignment(
196 unaligned_size: MemorySize,
197 max_alignment: MemoryAlignment,
198) -> MemorySize {
199 align_to(MemoryOffset(unaligned_size.0), max_alignment).to_size()
200}
201
202#[derive(Debug, Copy, Eq, PartialEq, Hash, Clone, Ord, PartialOrd)]
203pub struct HeapMemoryOffset(pub u32);
204
205impl HeapMemoryOffset {
206 #[must_use]
207 pub const fn to_size(&self) -> HeapMemorySize {
208 HeapMemorySize(self.0)
209 }
210}
211
212impl Display for HeapMemoryOffset {
213 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
214 write!(f, "+{:08X}]", self.0)
215 }
216}
217
218impl Add<HeapMemorySize> for HeapMemoryOffset {
219 type Output = Self;
220
221 fn add(self, rhs: HeapMemorySize) -> Self {
222 Self(self.0 + rhs.0)
223 }
224}
225
226impl Sub<Self> for HeapMemoryOffset {
227 type Output = Self;
228
229 fn sub(self, rhs: Self) -> Self {
230 assert!(rhs.0 <= self.0);
231 Self(self.0 - rhs.0)
232 }
233}
234
235impl HeapMemoryOffset {
236 #[must_use]
237 pub const fn as_size(&self) -> HeapMemorySize {
238 HeapMemorySize(self.0)
239 }
240}
241
242impl HeapMemoryOffset {
243 #[must_use]
244 pub fn add(&self, size: HeapMemorySize, alignment: MemoryAlignment) -> Self {
245 let new_start = align(self.0 as usize, alignment.into());
246 Self(new_start as u32 + size.0)
247 }
248}
249
250#[derive(Clone)]
251pub struct PointerLocation {
252 pub ptr_reg: TypedRegister,
253}
254
255impl PointerLocation {
256 #[must_use]
257 pub const fn new(ptr_reg: TypedRegister) -> Self {
258 Self { ptr_reg }
259 }
260 #[must_use]
261 pub const fn addressing(&self) -> u8 {
262 self.ptr_reg.addressing()
263 }
264}
265
266impl PointerLocation {
267 #[must_use]
268 pub fn memory_location(&self) -> MemoryLocation {
269 MemoryLocation {
270 base_ptr_reg: self.ptr_reg.clone(),
271 offset: MemoryOffset(0),
272 ty: self.ptr_reg.ty.clone(),
273 }
274 }
275}
276
277#[derive(Clone)]
278pub struct MemoryLocation {
279 pub base_ptr_reg: TypedRegister,
280 pub offset: MemoryOffset,
281 pub ty: VmType,
282}
283
284impl Display for MemoryLocation {
285 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
286 write!(f, "[{}+{} ({})]", self.base_ptr_reg, self.offset, self.ty)
287 }
288}
289
290impl MemoryLocation {
291 #[must_use]
292 pub const fn vm_type(&self) -> &VmType {
293 &self.ty
294 }
295
296 #[must_use]
297 pub fn unsafe_add_offset(&self, offset: MemoryOffset) -> Self {
298 Self {
299 base_ptr_reg: self.base_ptr_reg.clone(),
300 offset: self.offset.add(offset),
301 ty: self.ty.clone(),
302 }
303 }
304
305 #[must_use]
306 pub fn new_copy_over_whole_type_with_zero_offset(base_ptr_reg: TypedRegister) -> Self {
307 Self {
308 ty: base_ptr_reg.ty.clone(),
309 base_ptr_reg,
310 offset: MemoryOffset(0),
311 }
312 }
313}
314
315impl Debug for MemoryLocation {
316 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
317 write!(
318 f,
319 "MemLoc[{}+{:04X}] ({})",
320 self.base_ptr_reg, self.offset.0, self.ty
321 )
322 }
323}
324
325impl MemoryLocation {
326 #[must_use]
327 pub fn pointer_location(&self) -> Option<PointerLocation> {
328 if self.offset.0 == 0 {
329 Some(PointerLocation {
330 ptr_reg: self.base_ptr_reg.clone(),
331 })
332 } else {
333 None
334 }
335 }
336
337 #[must_use]
338 pub const fn reg(&self) -> &TypedRegister {
339 &self.base_ptr_reg
340 }
341
342 #[must_use]
343 pub const fn as_direct_register(&self) -> Option<&TypedRegister> {
344 if self.offset.0 == 0 {
345 Some(&self.base_ptr_reg)
346 } else {
347 None
348 }
349 }
350}
351
352#[derive(Clone)]
353pub struct ScalarMemoryLocation {
354 pub location: MemoryLocation,
355}
356#[derive(Clone)]
357pub struct AggregateMemoryLocation {
358 pub location: MemoryLocation,
359}
360
361impl AggregateMemoryLocation {
362 #[must_use]
363 pub const fn new(location: MemoryLocation) -> Self {
364 Self { location }
365 }
366}
367
368impl Display for AggregateMemoryLocation {
369 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
370 write!(f, "{}", self.location)
371 }
372}
373
374impl AggregateMemoryLocation {
375 #[must_use]
376 pub fn offset(&self, memory_offset: MemoryOffset, new_type: BasicTypeRef) -> Self {
377 let new_location = MemoryLocation {
378 base_ptr_reg: self.location.base_ptr_reg.clone(),
379 offset: self.location.offset + memory_offset,
380 ty: VmType::new_unknown_placement(new_type),
381 };
382 Self {
383 location: new_location,
384 }
385 }
386}
387
388pub enum ZFlagPolarity {
389 TrueWhenSet,
390 TrueWhenClear,
391}
392
393#[must_use]
394pub fn align_frame_addr(
395 memory_address: FrameMemoryAddress,
396 alignment: MemoryAlignment,
397) -> FrameMemoryAddress {
398 let raw_addr = align(memory_address.0 as usize, alignment.into());
399
400 FrameMemoryAddress(raw_addr as u32)
401}
402
403#[must_use]
404pub fn align_offset(memory_address: MemoryOffset, alignment: MemoryAlignment) -> MemoryOffset {
405 let raw_addr = align(memory_address.0 as usize, alignment.into());
406
407 MemoryOffset(raw_addr as u32)
408}
409
410#[derive(Clone)]
411pub struct Meta {
412 pub comment: String,
413 pub node: Node,
414}
415
416#[derive(Debug)]
417pub struct PatchPosition(pub InstructionPosition);
418
419#[derive(Debug, Clone, Eq, PartialEq, Hash)]
420pub struct InstructionPositionOffset(pub u32);
421
422#[derive(Debug, Clone, Eq, PartialEq, Hash)]
423pub struct InstructionRange {
424 pub start: InstructionPosition,
425 pub count: InstructionPositionOffset,
426}