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