comparison python/ppci/codegen/canon.py @ 301:6753763d3bec

merge codegen into ppci package
author Windel Bouwman
date Thu, 05 Dec 2013 17:02:38 +0100
parents python/codegen/canon.py@158068af716c
children e609d5296ee9
comparison
equal deleted inserted replaced
300:158068af716c 301:6753763d3bec
1 from .. 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)
23 # TODO: schedule here?
24
25 # Visit all nodes with some function:
26 # TODO: rewrite into visitor.
27
28 # Rewrite rewrites call instructions into Eseq instructions.
29
30
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)
62 return ir.Add(frame.fp, ir.Const(offset))
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
103
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))