1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
//! Intermediate Representation (IR) Instructions
//!
//! This module defines the intermediate representation used for code generation.
//! The IR is a simplified, architecture-agnostic representation of PowerPC instructions
//! that facilitates optimization and code generation.
//!
//! # Memory Optimizations
//! - `IRInstruction` uses `#[repr(u8)]` to save 3 bytes per enum variant
//! - `Address` and `Condition` use `#[repr(u8)]` for size optimization
//! - `IRFunction.parameters` uses `SmallVec<[u8; 8]>` (most functions have ≤8 parameters)
//! - `IRBasicBlock.successors` uses `SmallVec<[usize; 2]>` (most blocks have ≤2 successors)
//! - Block IDs use `u32` instead of `usize` to save space on 64-bit systems
//!
//! # IR Design
//! The IR is designed to be:
//! - **Simple**: Fewer instruction types than PowerPC ISA
//! - **Optimizable**: Easy to apply optimizations (dead code elimination, constant folding)
//! - **Target-agnostic**: Can be translated to any target architecture
use SmallVec;
/// Intermediate representation instruction.
///
/// # Memory Optimization
/// Uses `#[repr(u8)]` to reduce size from default enum size (typically 4-8 bytes)
/// to 1 byte for the discriminant, saving 3-7 bytes per instruction.
///
/// # Instruction Categories
/// - **Arithmetic**: Integer arithmetic operations
/// - **Memory**: Load and store operations
/// - **Control Flow**: Branches, calls, and returns
/// - **Floating Point**: FP arithmetic operations
/// - **Move**: Register moves and immediate loads
// Save 3-7 bytes per enum (default size -> 1 byte)
/// Memory address representation.
///
/// # Memory Optimization
/// Uses `#[repr(u8)]` to reduce size from default enum size to 1 byte.
///
/// # Address Modes
/// - **Register-relative**: Base register + signed offset (common for stack/local variables)
/// - **Constant**: Absolute address (for global variables, function addresses)
// Save 3-7 bytes per enum
/// Branch condition for conditional branches.
///
/// # Memory Optimization
/// Uses `#[repr(u8)]` to reduce size from default enum size to 1 byte.
// Save 3-7 bytes per enum
/// Intermediate representation of a function.
///
/// # Memory Optimization
/// - `parameters`: Uses `SmallVec<[u8; 8]>` - most functions have ≤8 parameters (PowerPC calling convention)
/// - `basic_blocks`: Uses `Vec` (functions can have many blocks, heap allocation is appropriate)
/// - `return_register`: Uses `Option<u8>` (1 byte + 1 byte discriminant = 2 bytes total)
///
/// # Function Structure
/// A function consists of:
/// - Name and address (for linking and debugging)
/// - Parameter list (register indices for PowerPC calling convention: r3-r10)
/// - Return register (if function returns a value, typically r3)
/// - Basic blocks (control flow graph nodes)
// Ensure C-compatible layout
/// Intermediate representation of a basic block.
///
/// # Memory Optimization
/// - `id`: Uses `u32` instead of `usize` to save 4 bytes on 64-bit systems
/// - `instructions`: Uses `Vec` (blocks can have many instructions)
/// - `successors`: Uses `SmallVec<[u32; 2]>` - most blocks have ≤2 successors (if-then-else, loop)
///
/// # Basic Block Properties
/// A basic block is a sequence of instructions with:
/// - Single entry point (first instruction)
/// - Single exit point (last instruction is a branch/return)
/// - No internal branches (linear execution)
// Ensure C-compatible layout