| 216 | return "array" if var.is_array() else "scalar" |
| 217 | |
| 218 | class Stack: |
| 219 | def __init__(self, check_stack_bounds: bool = False) -> None: |
| 220 | self.base_offset = PointerOffset.zero() |
| 221 | self.physical_sp = PointerOffset.zero() |
| 222 | self.logical_sp = PointerOffset.zero() |
| 223 | self.variables: list[Local] = [] |
| 224 | self.check_stack_bounds = check_stack_bounds |
| 225 | |
| 226 | def push_cache(self, cached_items:list[str], out: CWriter) -> None: |
| 227 | for i, name in enumerate(cached_items): |
| 228 | out.start_line() |
| 229 | out.emit(f"_PyStackRef _stack_item_{i} = {name};\n") |
| 230 | self.push(Local.register(f"_stack_item_{i}")) |
| 231 | |
| 232 | def drop(self, var: StackItem, check_liveness: bool) -> None: |
| 233 | self.logical_sp = self.logical_sp.pop(var) |
| 234 | if self.variables: |
| 235 | popped = self.variables.pop() |
| 236 | if popped.is_dead() or not var.used: |
| 237 | return |
| 238 | if check_liveness: |
| 239 | raise StackError(f"Dropping live value '{var.name}'") |
| 240 | |
| 241 | def pop(self, var: StackItem, out: CWriter) -> Local: |
| 242 | if self.variables: |
| 243 | top = self.variables[-1] |
| 244 | if var.is_array() != top.is_array() or top.size != var.size: |
| 245 | # Mismatch in variables |
| 246 | self.clear(out) |
| 247 | self.logical_sp = self.logical_sp.pop(var) |
| 248 | indirect = "&" if var.is_array() else "" |
| 249 | if self.variables: |
| 250 | popped = self.variables.pop() |
| 251 | assert var.is_array() == popped.is_array() and popped.size == var.size |
| 252 | if not var.used: |
| 253 | return popped |
| 254 | if popped.name != var.name: |
| 255 | rename = f"{var.name} = {popped.name};\n" |
| 256 | popped.item = var |
| 257 | else: |
| 258 | rename = "" |
| 259 | if not popped.in_local: |
| 260 | if popped.memory_offset is None: |
| 261 | popped.memory_offset = self.logical_sp |
| 262 | assert popped.memory_offset == self.logical_sp, (popped, self.as_comment()) |
| 263 | offset = popped.memory_offset - self.physical_sp |
| 264 | if var.is_array(): |
| 265 | defn = f"{var.name} = &stack_pointer[{offset.to_c()}];\n" |
| 266 | else: |
| 267 | defn = f"{var.name} = stack_pointer[{offset.to_c()}];\n" |
| 268 | popped.in_local = True |
| 269 | else: |
| 270 | defn = rename |
| 271 | out.emit(defn) |
| 272 | return popped |
| 273 | self.base_offset = self.logical_sp |
| 274 | if var.name in UNUSED or not var.used: |
| 275 | return Local.unused(var, self.base_offset) |
no outgoing calls
searching dependent graphs…