Mercurial > lcfOS
annotate python/codegen/canon.py @ 300:158068af716c
yafm
author | Windel Bouwman |
---|---|
date | Tue, 03 Dec 2013 18:00:22 +0100 |
parents | 9417caea2eb3 |
children |
rev | line source |
---|---|
275 | 1 import ir |
2 from itertools import chain | |
3 | |
4 def make(function, frame): | |
5 """ | |
6 Create canonicalized version of the IR-code. This means: | |
7 - Calls out of expressions. | |
8 - Other things? | |
9 """ | |
10 # Change the tree. This modifies the IR-tree! | |
11 # Move all parameters into registers | |
12 parmoves = [] | |
13 for p in function.arguments: | |
14 pt = newTemp() | |
15 frame.parMap[p] = pt | |
16 parmoves.append(ir.Move(pt, frame.argLoc(p.num))) | |
17 function.entry.instructions = parmoves + function.entry.instructions | |
18 | |
19 for block in function.Blocks: | |
20 for stmt in block.instructions: | |
21 rewriteStmt(stmt, frame) | |
22 linearize(block) | |
280
02385f62f250
Rework from str interface to Instruction interface
Windel Bouwman
parents:
279
diff
changeset
|
23 # TODO: schedule here? |
275 | 24 |
25 # Visit all nodes with some function: | |
26 # TODO: rewrite into visitor. | |
27 | |
28 # Rewrite rewrites call instructions into Eseq instructions. | |
29 | |
300 | 30 |
275 | 31 def rewriteStmt(stmt, frame): |
32 if isinstance(stmt, ir.Jump): | |
33 pass | |
34 elif isinstance(stmt, ir.CJump): | |
35 stmt.a = rewriteExp(stmt.a, frame) | |
36 stmt.b = rewriteExp(stmt.b, frame) | |
37 elif isinstance(stmt, ir.Move): | |
38 stmt.src = rewriteExp(stmt.src, frame) | |
39 stmt.dst = rewriteExp(stmt.dst, frame) | |
40 elif isinstance(stmt, ir.Terminator): | |
41 pass | |
42 elif isinstance(stmt, ir.Exp): | |
43 stmt.e = rewriteExp(stmt.e, frame) | |
44 else: | |
45 raise NotImplementedError('STMT NI: {}'.format(stmt)) | |
46 | |
47 newTemp = ir.NamedClassGenerator('canon_reg', ir.Temp).gen | |
48 | |
49 def rewriteExp(exp, frame): | |
50 if isinstance(exp, ir.Binop): | |
51 exp.a = rewriteExp(exp.a, frame) | |
52 exp.b = rewriteExp(exp.b, frame) | |
53 return exp | |
54 elif isinstance(exp, ir.Const): | |
55 return exp | |
56 elif isinstance(exp, ir.Temp): | |
57 return exp | |
58 elif isinstance(exp, ir.Parameter): | |
59 return frame.parMap[exp] | |
60 elif isinstance(exp, ir.LocalVariable): | |
61 offset = frame.allocVar(exp) | |
279 | 62 return ir.Add(frame.fp, ir.Const(offset)) |
275 | 63 elif isinstance(exp, ir.Mem): |
64 exp.e = rewriteExp(exp.e, frame) | |
65 return exp | |
66 elif isinstance(exp, ir.Call): | |
67 exp.arguments = [rewriteExp(p, frame) for p in exp.arguments] | |
68 # Rewrite call into eseq: | |
69 t = newTemp() | |
70 return ir.Eseq(ir.Move(t, exp), t) | |
71 else: | |
72 raise NotImplementedError('NI: {}'.format(exp)) | |
73 | |
74 # The flatten functions pull out seq instructions to the sequence list. | |
75 | |
76 def flattenExp(exp): | |
77 if isinstance(exp, ir.Binop): | |
78 exp.a, sa = flattenExp(exp.a) | |
79 exp.b, sb = flattenExp(exp.b) | |
80 return exp, sa + sb | |
81 elif isinstance(exp, ir.Temp): | |
82 return exp, [] | |
83 elif isinstance(exp, ir.Const): | |
84 return exp, [] | |
85 elif isinstance(exp, ir.Mem): | |
86 exp.e, s = flattenExp(exp.e) | |
87 return exp, s | |
88 elif isinstance(exp, ir.Eseq): | |
89 s = flattenStmt(exp.stmt) | |
90 exp.e, se = flattenExp(exp.e) | |
91 return exp.e, s + se | |
92 elif isinstance(exp, ir.Call): | |
93 sp = [] | |
94 p = [] | |
95 for p_, sp_ in (flattenExp(p) for p in exp.arguments): | |
96 p.append(p_) | |
97 sp.extend(sp_) | |
98 exp.arguments = p | |
99 return exp, sp | |
100 else: | |
101 raise NotImplementedError('NI: {}'.format(exp)) | |
102 | |
300 | 103 |
275 | 104 def flattenStmt(stmt): |
105 if isinstance(stmt, ir.Jump): | |
106 return [stmt] | |
107 elif isinstance(stmt, ir.CJump): | |
108 stmt.a, sa = flattenExp(stmt.a) | |
109 stmt.b, sb = flattenExp(stmt.b) | |
110 return sa + sb + [stmt] | |
111 elif isinstance(stmt, ir.Move): | |
112 stmt.dst, sd = flattenExp(stmt.dst) | |
113 stmt.src, ss = flattenExp(stmt.src) | |
114 return sd + ss + [stmt] | |
115 elif isinstance(stmt, ir.Terminator): | |
116 return [stmt] | |
117 elif isinstance(stmt, ir.Exp): | |
118 stmt.e, se = flattenExp(stmt.e) | |
119 return se + [stmt] | |
120 else: | |
121 raise NotImplementedError('STMT NI: {}'.format(stmt)) | |
122 | |
123 | |
124 def linearize(block): | |
125 """ | |
126 Move seq instructions to top and flatten these in an instruction list | |
127 """ | |
128 i = list(flattenStmt(s) for s in block.instructions) | |
129 block.instructions = list(chain.from_iterable(i)) |