Skip to content

Commit caea830

Browse files
authored
Merge pull request #658 from boriel/refact/refact_code
Refact/refact code
2 parents 7e6431d + c927e37 commit caea830

9 files changed

Lines changed: 415 additions & 403 deletions

File tree

docs/library/windowpaint.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ Where
3030

3131
```
3232
SUB windowPaint(x as uByte,y as uByte, width as uByte, height as uByte, inkCol as ubyte, paperCol as uByte, isBright as uByte, isFlash as uByte)
33-
paint(x,y,width,height,(isFlash<<7+isBright<<6+paperCol<<3+inkCol))
33+
paint(x,y,width,height,(isFlash<<7) bOR (isBright<<6) bOR (paperCol<<3) bOR inkCol)
3434
END SUB
3535
3636

src/arch/z80/optimizer/__init__.py

Lines changed: 1 addition & 243 deletions
Original file line numberDiff line numberDiff line change
@@ -1,243 +1 @@
1-
# -*- coding: utf-8 -*-
2-
3-
from src.api.config import OPTIONS
4-
from src.api.debug import __DEBUG__
5-
from src.api.utils import flatten_list
6-
7-
from ..peephole import engine
8-
from . import basicblock
9-
from .basicblock import DummyBasicBlock
10-
from .common import JUMP_LABELS, LABELS, MEMORY
11-
from .helpers import ALL_REGS, END_PROGRAM_LABEL
12-
from .labelinfo import LabelInfo
13-
from .patterns import RE_LABEL, RE_PRAGMA
14-
15-
16-
def init():
17-
LABELS.clear()
18-
JUMP_LABELS.clear()
19-
20-
LABELS["*START*"] = LabelInfo("*START*", 0, DummyBasicBlock(ALL_REGS, ALL_REGS)) # Special START BLOCK
21-
LABELS["*__END_PROGRAM*"] = LabelInfo("__END_PROGRAM", 0, DummyBasicBlock(ALL_REGS, list("bc")))
22-
23-
# SOME Global modules initialization
24-
LABELS["__ADDF"] = LabelInfo("__ADDF", 0, DummyBasicBlock(ALL_REGS, list("aedbc")))
25-
LABELS["__SUBF"] = LabelInfo("__SUBF", 0, DummyBasicBlock(ALL_REGS, list("aedbc")))
26-
LABELS["__DIVF"] = LabelInfo("__DIVF", 0, DummyBasicBlock(ALL_REGS, list("aedbc")))
27-
LABELS["__MULF"] = LabelInfo("__MULF", 0, DummyBasicBlock(ALL_REGS, list("aedbc")))
28-
LABELS["__GEF"] = LabelInfo("__GEF", 0, DummyBasicBlock(ALL_REGS, list("aedbc")))
29-
LABELS["__GTF"] = LabelInfo("__GTF", 0, DummyBasicBlock(ALL_REGS, list("aedbc")))
30-
LABELS["__EQF"] = LabelInfo("__EQF", 0, DummyBasicBlock(ALL_REGS, list("aedbc")))
31-
LABELS["__STOREF"] = LabelInfo("__STOREF", 0, DummyBasicBlock(ALL_REGS, list("hlaedbc")))
32-
LABELS["PRINT_AT"] = LabelInfo("PRINT_AT", 0, DummyBasicBlock(ALL_REGS, list("a")))
33-
LABELS["INK"] = LabelInfo("INK", 0, DummyBasicBlock(ALL_REGS, list("a")))
34-
LABELS["INK_TMP"] = LabelInfo("INK_TMP", 0, DummyBasicBlock(ALL_REGS, list("a")))
35-
LABELS["PAPER"] = LabelInfo("PAPER", 0, DummyBasicBlock(ALL_REGS, list("a")))
36-
LABELS["PAPER_TMP"] = LabelInfo("PAPER_TMP", 0, DummyBasicBlock(ALL_REGS, list("a")))
37-
LABELS["RND"] = LabelInfo("RND", 0, DummyBasicBlock(ALL_REGS, []))
38-
LABELS["INKEY"] = LabelInfo("INKEY", 0, DummyBasicBlock(ALL_REGS, []))
39-
LABELS["PLOT"] = LabelInfo("PLOT", 0, DummyBasicBlock(ALL_REGS, ["a"]))
40-
LABELS["DRAW"] = LabelInfo("DRAW", 0, DummyBasicBlock(ALL_REGS, ["h", "l"]))
41-
LABELS["DRAW3"] = LabelInfo("DRAW3", 0, DummyBasicBlock(ALL_REGS, list("abcde")))
42-
LABELS["__ARRAY"] = LabelInfo("__ARRAY", 0, DummyBasicBlock(ALL_REGS, ["h", "l"]))
43-
LABELS["__MEMCPY"] = LabelInfo("__MEMCPY", 0, DummyBasicBlock(list("bcdefhl"), list("bcdehl")))
44-
LABELS["__PLOADF"] = LabelInfo("__PLOADF", 0, DummyBasicBlock(ALL_REGS, ALL_REGS)) # Special START BLOCK
45-
LABELS["__PSTOREF"] = LabelInfo("__PSTOREF", 0, DummyBasicBlock(ALL_REGS, ALL_REGS)) # Special START BLOCK
46-
47-
48-
def cleanupmem(initial_memory):
49-
"""Cleans up initial memory. Each label must be
50-
ALONE. Each instruction must have an space, etc...
51-
"""
52-
i = 0
53-
while i < len(initial_memory):
54-
tmp = initial_memory[i]
55-
match = RE_LABEL.match(tmp)
56-
if not match:
57-
i += 1
58-
continue
59-
60-
if tmp.rstrip() == match.group():
61-
i += 1
62-
continue
63-
64-
initial_memory[i] = tmp[match.end() :]
65-
initial_memory.insert(i, match.group())
66-
i += 1
67-
68-
69-
def cleanup_local_labels(block):
70-
"""Traverses memory, to make any local label a unique
71-
global one. At this point there's only a single code
72-
block
73-
"""
74-
global PROC_COUNTER
75-
76-
stack = [[]]
77-
hashes = [{}]
78-
stackprc = [PROC_COUNTER]
79-
used = [{}] # List of hashes of unresolved labels per scope
80-
81-
MEMORY = block.mem
82-
83-
for cell in MEMORY:
84-
if cell.inst.upper() == "PROC":
85-
stack += [[]]
86-
hashes += [{}]
87-
stackprc += [PROC_COUNTER]
88-
used += [{}]
89-
PROC_COUNTER += 1
90-
continue
91-
92-
if cell.inst.upper() == "ENDP":
93-
if len(stack) > 1: # There might be unbalanced stack due to syntax errors
94-
for label in used[-1].keys():
95-
if label in stack[-1]:
96-
newlabel = hashes[-1][label]
97-
for cell in used[-1][label]:
98-
cell.replace_label(label, newlabel)
99-
100-
stack.pop()
101-
hashes.pop()
102-
stackprc.pop()
103-
used.pop()
104-
continue
105-
106-
tmp = cell.asm.asm
107-
if tmp.upper()[:5] == "LOCAL":
108-
tmp = tmp[5:].split(",")
109-
for lbl in tmp:
110-
lbl = lbl.strip()
111-
if lbl in stack[-1]:
112-
continue
113-
stack[-1] += [lbl]
114-
hashes[-1][lbl] = "PROC%i." % stackprc[-1] + lbl
115-
if used[-1].get(lbl, None) is None:
116-
used[-1][lbl] = []
117-
118-
cell.asm = ";" + cell.asm # Remove it
119-
continue
120-
121-
if cell.is_label:
122-
label = cell.inst
123-
for i in range(len(stack) - 1, -1, -1):
124-
if label in stack[i]:
125-
label = hashes[i][label]
126-
cell.asm = label + ":"
127-
break
128-
continue
129-
130-
for label in cell.used_labels:
131-
labelUsed = False
132-
for i in range(len(stack) - 1, -1, -1):
133-
if label in stack[i]:
134-
newlabel = hashes[i][label]
135-
cell.replace_label(label, newlabel)
136-
labelUsed = True
137-
break
138-
139-
if not labelUsed:
140-
if used[-1].get(label, None) is None:
141-
used[-1][label] = []
142-
143-
used[-1][label] += [cell]
144-
145-
for i in range(len(MEMORY) - 1, -1, -1):
146-
if MEMORY[i].asm.asm[0] == ";":
147-
MEMORY.pop(i)
148-
149-
block.mem = MEMORY
150-
block.asm = [x.asm for x in MEMORY if len(x.asm)]
151-
152-
153-
def get_labels(basic_block):
154-
"""Traverses memory, to annotate all the labels in the global
155-
LABELS table
156-
"""
157-
for i, cell in enumerate(basic_block):
158-
if cell.is_label:
159-
label = cell.inst
160-
LABELS[label] = LabelInfo(label, cell.addr, basic_block, i) # Stores it globally
161-
162-
163-
def initialize_memory(basic_block):
164-
"""Initializes global memory array with the one in the main (initial) basic_block"""
165-
global MEMORY
166-
167-
init()
168-
MEMORY = basic_block.mem
169-
get_labels(basic_block)
170-
171-
172-
def optimize(initial_memory: list[str]) -> str:
173-
"""This will remove useless instructions"""
174-
global BLOCKS
175-
global PROC_COUNTER
176-
177-
del MEMORY[:]
178-
PROC_COUNTER = 0
179-
180-
cleanupmem(initial_memory)
181-
if OPTIONS.optimization_level <= 2: # if -O2 or lower, do nothing and return
182-
return "\n".join(x for x in initial_memory if not RE_PRAGMA.match(x))
183-
184-
basicblock.BasicBlock.clean_asm_args = OPTIONS.optimization_level > 3
185-
bb = basicblock.BasicBlock(initial_memory)
186-
cleanup_local_labels(bb)
187-
initialize_memory(bb)
188-
189-
BLOCKS = basic_blocks = basicblock.get_basic_blocks(bb) # 1st partition the Basic Blocks
190-
191-
for b in basic_blocks:
192-
__DEBUG__("--- BASIC BLOCK: {} ---".format(b.id), 1)
193-
__DEBUG__("Code:\n" + "\n".join(" {}".format(x) for x in b.code), 1)
194-
__DEBUG__("Requires: {}".format(b.requires()), 1)
195-
__DEBUG__("Destroys: {}".format(b.destroys()), 1)
196-
__DEBUG__("Label goes: {}".format(b.label_goes), 1)
197-
__DEBUG__("Comes from: {}".format([x.id for x in b.comes_from]), 1)
198-
__DEBUG__("Goes to: {}".format([x.id for x in b.goes_to]), 1)
199-
__DEBUG__("Next: {}".format(b.next.id if b.next is not None else None), 1)
200-
__DEBUG__("Size: {} Time: {}".format(b.sizeof, b.max_tstates), 1)
201-
__DEBUG__("--- END ---", 1)
202-
203-
LABELS["*START*"].basic_block.add_goes_to(basic_blocks[0])
204-
LABELS["*START*"].basic_block.next = basic_blocks[0]
205-
206-
basic_blocks[0].prev = LABELS["*START*"].basic_block
207-
if END_PROGRAM_LABEL in LABELS:
208-
LABELS[END_PROGRAM_LABEL].basic_block.add_goes_to(LABELS["*__END_PROGRAM*"].basic_block)
209-
210-
# In O3 we simplify the graph by reducing jumps over jumps
211-
for label in JUMP_LABELS:
212-
block = LABELS[label].basic_block
213-
if isinstance(block, DummyBasicBlock):
214-
continue
215-
216-
# The instruction that starts this block must be one of jr / jp
217-
first = block.get_next_exec_instruction()
218-
if first is None or first.inst not in ("jp", "jr"):
219-
continue
220-
221-
for blk in list(LABELS[label].used_by):
222-
if not first.condition_flag or blk[-1].condition_flag == first.condition_flag:
223-
new_label = first.opers[0]
224-
blk[-1].asm = blk[-1].code.replace(label, new_label)
225-
block.delete_comes_from(blk)
226-
LABELS[label].used_by.remove(blk)
227-
LABELS[new_label].used_by.add(blk)
228-
blk.add_goes_to(LABELS[new_label].basic_block)
229-
230-
for x in basic_blocks:
231-
x.compute_cpu_state()
232-
233-
filtered_patterns_list = [p for p in engine.PATTERNS if OPTIONS.optimization_level >= p.level >= 3]
234-
for x in basic_blocks:
235-
x.optimize(filtered_patterns_list)
236-
237-
for x in basic_blocks:
238-
if x.comes_from == [] and len([y for y in JUMP_LABELS if x is LABELS[y].basic_block]):
239-
x.ignored = True
240-
241-
return "\n".join(
242-
[y for y in flatten_list([x.code for x in basic_blocks if not x.ignored]) if not RE_PRAGMA.match(y)]
243-
)
1+
from .main import init, optimize

0 commit comments

Comments
 (0)