annotate python/x86.py @ 177:460db5669efa

Added clean pass for IR
author Windel Bouwman
date Mon, 22 Apr 2013 23:54:54 +0200
parents 3eb06f5fb987
children c694ec551f34
rev   line source
157
8f3924b6076e Added some code generator things
Windel Bouwman
parents:
diff changeset
1 import ppci
158
9683a4cd848f Added some functions for code generation
Windel Bouwman
parents: 157
diff changeset
2 import ir
173
c1d2b6b9f9a7 Rework into passes
Windel Bouwman
parents: 171
diff changeset
3 import registerallocator
158
9683a4cd848f Added some functions for code generation
Windel Bouwman
parents: 157
diff changeset
4
177
460db5669efa Added clean pass for IR
Windel Bouwman
parents: 174
diff changeset
5 # Instruction selection with DAG (Directed Acyclic Graph)
460db5669efa Added clean pass for IR
Windel Bouwman
parents: 174
diff changeset
6 class DagLeaf:
460db5669efa Added clean pass for IR
Windel Bouwman
parents: 174
diff changeset
7 def __init__(self, v):
460db5669efa Added clean pass for IR
Windel Bouwman
parents: 174
diff changeset
8 self.v = v
460db5669efa Added clean pass for IR
Windel Bouwman
parents: 174
diff changeset
9
460db5669efa Added clean pass for IR
Windel Bouwman
parents: 174
diff changeset
10 class DagNode:
460db5669efa Added clean pass for IR
Windel Bouwman
parents: 174
diff changeset
11 def __init__(self, name):
460db5669efa Added clean pass for IR
Windel Bouwman
parents: 174
diff changeset
12 self.name = name
460db5669efa Added clean pass for IR
Windel Bouwman
parents: 174
diff changeset
13 self.children = []
460db5669efa Added clean pass for IR
Windel Bouwman
parents: 174
diff changeset
14 def __repr__(self):
460db5669efa Added clean pass for IR
Windel Bouwman
parents: 174
diff changeset
15 return str(self.name)
460db5669efa Added clean pass for IR
Windel Bouwman
parents: 174
diff changeset
16
460db5669efa Added clean pass for IR
Windel Bouwman
parents: 174
diff changeset
17 class Dag:
460db5669efa Added clean pass for IR
Windel Bouwman
parents: 174
diff changeset
18 def __init__(self, bb):
460db5669efa Added clean pass for IR
Windel Bouwman
parents: 174
diff changeset
19 self.mapping = {}
460db5669efa Added clean pass for IR
Windel Bouwman
parents: 174
diff changeset
20 self.buildFromBB(bb)
460db5669efa Added clean pass for IR
Windel Bouwman
parents: 174
diff changeset
21 def buildFromBB(self, bb):
460db5669efa Added clean pass for IR
Windel Bouwman
parents: 174
diff changeset
22 for ins in bb.Instructions:
460db5669efa Added clean pass for IR
Windel Bouwman
parents: 174
diff changeset
23 if type(ins) is ir.BinaryOperator:
460db5669efa Added clean pass for IR
Windel Bouwman
parents: 174
diff changeset
24 if not ins.value1 in self.mapping:
460db5669efa Added clean pass for IR
Windel Bouwman
parents: 174
diff changeset
25 self.mapping[ins.value1] = DagNode(ins.value1)
460db5669efa Added clean pass for IR
Windel Bouwman
parents: 174
diff changeset
26 if not ins.value2 in self.mapping:
460db5669efa Added clean pass for IR
Windel Bouwman
parents: 174
diff changeset
27 self.mapping[ins.value2] = DagNode(ins.value2)
460db5669efa Added clean pass for IR
Windel Bouwman
parents: 174
diff changeset
28 # look for op with left and right operand the same:
460db5669efa Added clean pass for IR
Windel Bouwman
parents: 174
diff changeset
29 N = None
460db5669efa Added clean pass for IR
Windel Bouwman
parents: 174
diff changeset
30 lnode = self.mapping[ins.value1]
460db5669efa Added clean pass for IR
Windel Bouwman
parents: 174
diff changeset
31 rnode = self.mapping[ins.value2]
460db5669efa Added clean pass for IR
Windel Bouwman
parents: 174
diff changeset
32 for node in self.mapping.values():
460db5669efa Added clean pass for IR
Windel Bouwman
parents: 174
diff changeset
33 if node.name == ins.operation:
460db5669efa Added clean pass for IR
Windel Bouwman
parents: 174
diff changeset
34 if node.children[0] == lnode and node.children[1] == rnode:
460db5669efa Added clean pass for IR
Windel Bouwman
parents: 174
diff changeset
35 N = node
460db5669efa Added clean pass for IR
Windel Bouwman
parents: 174
diff changeset
36 break
460db5669efa Added clean pass for IR
Windel Bouwman
parents: 174
diff changeset
37 if not N:
460db5669efa Added clean pass for IR
Windel Bouwman
parents: 174
diff changeset
38 # Create a node.
460db5669efa Added clean pass for IR
Windel Bouwman
parents: 174
diff changeset
39 N = DagNode(ins.operation)
460db5669efa Added clean pass for IR
Windel Bouwman
parents: 174
diff changeset
40 N.children.append(lnode)
460db5669efa Added clean pass for IR
Windel Bouwman
parents: 174
diff changeset
41 N.children.append(rnode)
460db5669efa Added clean pass for IR
Windel Bouwman
parents: 174
diff changeset
42 self.mapping[ins.result] = N
460db5669efa Added clean pass for IR
Windel Bouwman
parents: 174
diff changeset
43 else:
460db5669efa Added clean pass for IR
Windel Bouwman
parents: 174
diff changeset
44 pass
460db5669efa Added clean pass for IR
Windel Bouwman
parents: 174
diff changeset
45 def dumpgv(self, outf):
460db5669efa Added clean pass for IR
Windel Bouwman
parents: 174
diff changeset
46 outf.write('subgraph {0} {{\n'.format(id(self)))
460db5669efa Added clean pass for IR
Windel Bouwman
parents: 174
diff changeset
47 for node in self.mapping.values():
460db5669efa Added clean pass for IR
Windel Bouwman
parents: 174
diff changeset
48 outf.write('{0} [label="{1}"];\n'.format(id(node), node.name))
460db5669efa Added clean pass for IR
Windel Bouwman
parents: 174
diff changeset
49 for c in node.children:
460db5669efa Added clean pass for IR
Windel Bouwman
parents: 174
diff changeset
50 outf.write('{0} -> {1};\n'.format(id(node), id(c)))
460db5669efa Added clean pass for IR
Windel Bouwman
parents: 174
diff changeset
51 outf.write('label="dag"}\n')
460db5669efa Added clean pass for IR
Windel Bouwman
parents: 174
diff changeset
52
460db5669efa Added clean pass for IR
Windel Bouwman
parents: 174
diff changeset
53 def insSelect(mod):
460db5669efa Added clean pass for IR
Windel Bouwman
parents: 174
diff changeset
54 """ Create DAG from ir-code """
460db5669efa Added clean pass for IR
Windel Bouwman
parents: 174
diff changeset
55 for bb in mod.BasicBlocks:
460db5669efa Added clean pass for IR
Windel Bouwman
parents: 174
diff changeset
56 print(bb)
460db5669efa Added clean pass for IR
Windel Bouwman
parents: 174
diff changeset
57 dag = Dag(bb)
460db5669efa Added clean pass for IR
Windel Bouwman
parents: 174
diff changeset
58 print(dag.mapping)
460db5669efa Added clean pass for IR
Windel Bouwman
parents: 174
diff changeset
59 bb.dag = dag
460db5669efa Added clean pass for IR
Windel Bouwman
parents: 174
diff changeset
60
460db5669efa Added clean pass for IR
Windel Bouwman
parents: 174
diff changeset
61 # x86 specific:
158
9683a4cd848f Added some functions for code generation
Windel Bouwman
parents: 157
diff changeset
62 class AsmLabel:
9683a4cd848f Added some functions for code generation
Windel Bouwman
parents: 157
diff changeset
63 def __init__(self, lab):
9683a4cd848f Added some functions for code generation
Windel Bouwman
parents: 157
diff changeset
64 self.lab = lab
9683a4cd848f Added some functions for code generation
Windel Bouwman
parents: 157
diff changeset
65 def __repr__(self):
9683a4cd848f Added some functions for code generation
Windel Bouwman
parents: 157
diff changeset
66 return '{0}:'.format(self.lab)
9683a4cd848f Added some functions for code generation
Windel Bouwman
parents: 157
diff changeset
67
9683a4cd848f Added some functions for code generation
Windel Bouwman
parents: 157
diff changeset
68 class Op:
171
3eb9b9e2958d Improved IR code
Windel Bouwman
parents: 160
diff changeset
69 def __init__(self, op, dst, src):
158
9683a4cd848f Added some functions for code generation
Windel Bouwman
parents: 157
diff changeset
70 self.op = op
171
3eb9b9e2958d Improved IR code
Windel Bouwman
parents: 160
diff changeset
71 self.src = src
3eb9b9e2958d Improved IR code
Windel Bouwman
parents: 160
diff changeset
72 self.dst = dst
158
9683a4cd848f Added some functions for code generation
Windel Bouwman
parents: 157
diff changeset
73 def __repr__(self):
171
3eb9b9e2958d Improved IR code
Windel Bouwman
parents: 160
diff changeset
74 return '{0} {1}, {2}'.format(self.op, self.dst, self.src)
3eb9b9e2958d Improved IR code
Windel Bouwman
parents: 160
diff changeset
75
3eb9b9e2958d Improved IR code
Windel Bouwman
parents: 160
diff changeset
76 class Jmp:
3eb9b9e2958d Improved IR code
Windel Bouwman
parents: 160
diff changeset
77 def __init__(self, j, target):
3eb9b9e2958d Improved IR code
Windel Bouwman
parents: 160
diff changeset
78 self.j = j
3eb9b9e2958d Improved IR code
Windel Bouwman
parents: 160
diff changeset
79 self.target = target
3eb9b9e2958d Improved IR code
Windel Bouwman
parents: 160
diff changeset
80 def __repr__(self):
3eb9b9e2958d Improved IR code
Windel Bouwman
parents: 160
diff changeset
81 return '{0} {1}'.format(self.j, self.target)
157
8f3924b6076e Added some code generator things
Windel Bouwman
parents:
diff changeset
82
8f3924b6076e Added some code generator things
Windel Bouwman
parents:
diff changeset
83 class X86CodeGen:
8f3924b6076e Added some code generator things
Windel Bouwman
parents:
diff changeset
84 def __init__(self, diag):
8f3924b6076e Added some code generator things
Windel Bouwman
parents:
diff changeset
85 self.diag = diag
160
10330be89bc2 Started from scratch with code edit
Windel Bouwman
parents: 158
diff changeset
86 self.regs = ['rax', 'rbx', 'rcx', 'rdx']
157
8f3924b6076e Added some code generator things
Windel Bouwman
parents:
diff changeset
87
158
9683a4cd848f Added some functions for code generation
Windel Bouwman
parents: 157
diff changeset
88 def emit(self, i):
9683a4cd848f Added some functions for code generation
Windel Bouwman
parents: 157
diff changeset
89 self.asm.append(i)
9683a4cd848f Added some functions for code generation
Windel Bouwman
parents: 157
diff changeset
90
171
3eb9b9e2958d Improved IR code
Windel Bouwman
parents: 160
diff changeset
91 def genBin(self, ir):
158
9683a4cd848f Added some functions for code generation
Windel Bouwman
parents: 157
diff changeset
92 self.asm = []
171
3eb9b9e2958d Improved IR code
Windel Bouwman
parents: 160
diff changeset
93 # Allocate registers:
177
460db5669efa Added clean pass for IR
Windel Bouwman
parents: 174
diff changeset
94 insSelect(ir)
173
c1d2b6b9f9a7 Rework into passes
Windel Bouwman
parents: 171
diff changeset
95 ra = registerallocator.RegisterAllocator()
174
3eb06f5fb987 Added memory alloc for locals
Windel Bouwman
parents: 173
diff changeset
96 # TODO: do not register allocate on intermediate code:
173
c1d2b6b9f9a7 Rework into passes
Windel Bouwman
parents: 171
diff changeset
97 ra.registerAllocate(ir, self.regs)
171
3eb9b9e2958d Improved IR code
Windel Bouwman
parents: 160
diff changeset
98 self.genModule(ir)
3eb9b9e2958d Improved IR code
Windel Bouwman
parents: 160
diff changeset
99 return self.asm
157
8f3924b6076e Added some code generator things
Windel Bouwman
parents:
diff changeset
100
171
3eb9b9e2958d Improved IR code
Windel Bouwman
parents: 160
diff changeset
101 def genModule(self, ir):
174
3eb06f5fb987 Added memory alloc for locals
Windel Bouwman
parents: 173
diff changeset
102 for f in ir.Functions:
3eb06f5fb987 Added memory alloc for locals
Windel Bouwman
parents: 173
diff changeset
103 self.genFunction(f)
158
9683a4cd848f Added some functions for code generation
Windel Bouwman
parents: 157
diff changeset
104 def genFunction(self, f):
9683a4cd848f Added some functions for code generation
Windel Bouwman
parents: 157
diff changeset
105 self.emit('global {0}'.format(f.name))
9683a4cd848f Added some functions for code generation
Windel Bouwman
parents: 157
diff changeset
106 self.emit(AsmLabel(f.name))
174
3eb06f5fb987 Added memory alloc for locals
Windel Bouwman
parents: 173
diff changeset
107 self.emit(Jmp('jmp', f.entry.name))
158
9683a4cd848f Added some functions for code generation
Windel Bouwman
parents: 157
diff changeset
108 for bb in f.BasicBlocks:
9683a4cd848f Added some functions for code generation
Windel Bouwman
parents: 157
diff changeset
109 self.genBB(bb)
9683a4cd848f Added some functions for code generation
Windel Bouwman
parents: 157
diff changeset
110 def genBB(self, bb):
171
3eb9b9e2958d Improved IR code
Windel Bouwman
parents: 160
diff changeset
111 self.emit(AsmLabel(bb.name))
158
9683a4cd848f Added some functions for code generation
Windel Bouwman
parents: 157
diff changeset
112 for i in bb.Instructions:
9683a4cd848f Added some functions for code generation
Windel Bouwman
parents: 157
diff changeset
113 self.genIns(i)
9683a4cd848f Added some functions for code generation
Windel Bouwman
parents: 157
diff changeset
114 def genIns(self, i):
9683a4cd848f Added some functions for code generation
Windel Bouwman
parents: 157
diff changeset
115 if type(i) is ir.BinaryOperator:
171
3eb9b9e2958d Improved IR code
Windel Bouwman
parents: 160
diff changeset
116 ops = {'+':'add', '-':'sub', '*':'mul'}
3eb9b9e2958d Improved IR code
Windel Bouwman
parents: 160
diff changeset
117 if i.operation in ops:
3eb9b9e2958d Improved IR code
Windel Bouwman
parents: 160
diff changeset
118 self.emit(Op('mov', i.result.reg, i.value1.reg))
3eb9b9e2958d Improved IR code
Windel Bouwman
parents: 160
diff changeset
119 self.emit(Op(ops[i.operation], i.result.reg, i.value2.reg))
3eb9b9e2958d Improved IR code
Windel Bouwman
parents: 160
diff changeset
120 else:
3eb9b9e2958d Improved IR code
Windel Bouwman
parents: 160
diff changeset
121 raise NotImplementedError('op {0}'.format(i.operation))
3eb9b9e2958d Improved IR code
Windel Bouwman
parents: 160
diff changeset
122 elif type(i) is ir.Load:
174
3eb06f5fb987 Added memory alloc for locals
Windel Bouwman
parents: 173
diff changeset
123 self.emit(Op('mov', i.value, '[{0}]'.format(i.location)))
171
3eb9b9e2958d Improved IR code
Windel Bouwman
parents: 160
diff changeset
124 elif type(i) is ir.Return:
158
9683a4cd848f Added some functions for code generation
Windel Bouwman
parents: 157
diff changeset
125 self.emit('ret')
171
3eb9b9e2958d Improved IR code
Windel Bouwman
parents: 160
diff changeset
126 elif type(i) is ir.Call:
160
10330be89bc2 Started from scratch with code edit
Windel Bouwman
parents: 158
diff changeset
127 self.emit('call')
171
3eb9b9e2958d Improved IR code
Windel Bouwman
parents: 160
diff changeset
128 elif type(i) is ir.ImmLoad:
3eb9b9e2958d Improved IR code
Windel Bouwman
parents: 160
diff changeset
129 self.emit(Op('mov', i.target, i.value))
3eb9b9e2958d Improved IR code
Windel Bouwman
parents: 160
diff changeset
130 elif type(i) is ir.Store:
174
3eb06f5fb987 Added memory alloc for locals
Windel Bouwman
parents: 173
diff changeset
131 self.emit(Op('mov', '[{0}]'.format(i.location), i.value))
171
3eb9b9e2958d Improved IR code
Windel Bouwman
parents: 160
diff changeset
132 elif type(i) is ir.ConditionalBranch:
3eb9b9e2958d Improved IR code
Windel Bouwman
parents: 160
diff changeset
133 self.emit(Op('cmp', i.a, i.b))
3eb9b9e2958d Improved IR code
Windel Bouwman
parents: 160
diff changeset
134 jmps = {'>':'jg', '<':'jl', '==':'je'}
3eb9b9e2958d Improved IR code
Windel Bouwman
parents: 160
diff changeset
135 if i.cond in jmps:
3eb9b9e2958d Improved IR code
Windel Bouwman
parents: 160
diff changeset
136 j = jmps[i.cond]
3eb9b9e2958d Improved IR code
Windel Bouwman
parents: 160
diff changeset
137 self.emit(Jmp(j, i.lab1.name))
3eb9b9e2958d Improved IR code
Windel Bouwman
parents: 160
diff changeset
138 else:
3eb9b9e2958d Improved IR code
Windel Bouwman
parents: 160
diff changeset
139 raise NotImplementedError('condition {0}'.format(i.cond))
3eb9b9e2958d Improved IR code
Windel Bouwman
parents: 160
diff changeset
140 self.emit(Jmp('jmp', i.lab2.name))
3eb9b9e2958d Improved IR code
Windel Bouwman
parents: 160
diff changeset
141 elif type(i) is ir.Branch:
3eb9b9e2958d Improved IR code
Windel Bouwman
parents: 160
diff changeset
142 self.emit(Jmp('jmp', i.target.name))
174
3eb06f5fb987 Added memory alloc for locals
Windel Bouwman
parents: 173
diff changeset
143 elif type(i) is ir.Alloc:
3eb06f5fb987 Added memory alloc for locals
Windel Bouwman
parents: 173
diff changeset
144 pass
158
9683a4cd848f Added some functions for code generation
Windel Bouwman
parents: 157
diff changeset
145 else:
171
3eb9b9e2958d Improved IR code
Windel Bouwman
parents: 160
diff changeset
146 raise NotImplementedError('{0}'.format(i))
158
9683a4cd848f Added some functions for code generation
Windel Bouwman
parents: 157
diff changeset
147