comparison python/ir.py @ 277:046017431c6a

Started register allocator
author Windel Bouwman
date Thu, 26 Sep 2013 21:14:25 +0200
parents
children 2ccd57b1d78c
comparison
equal deleted inserted replaced
276:56d37ed4b4d2 277:046017431c6a
1 """
2 Intermediate representation (IR) code classes.
3 """
4
5
6 def dumpgv(m, outf):
7 print('digraph G ', file=outf)
8 print('{', file=outf)
9 for f in m.Functions:
10 print('{} [label="{}" shape=box3d]'.format(id(f), f),file=outf)
11 for bb in f.Blocks:
12 contents = str(bb) + '\n'
13 contents += '\n'.join([str(i) for i in bb.Instructions])
14 outf.write('{0} [shape=note label="{1}"];\n'.format(id(bb), contents))
15 for successor in bb.Successors:
16 print('"{}" -> "{}"\n'.format(id(bb), id(successor)), file=outf)
17
18 outf.write('"{}" -> "{}" [label="entry"]\n'.format(id(f), id(f.entry)))
19 print('}', file=outf)
20
21
22 class Module:
23 """ Main container of variables and functions. """
24 def __init__(self, name):
25 self.name = name
26 self.funcs = []
27 self.variables = []
28
29 def __repr__(self):
30 return 'IR-module [{0}]'.format(self.name)
31
32 def addFunc(self, f):
33 self.funcs.append(f)
34
35 addFunction = addFunc
36
37 def addVariable(self, v):
38 self.variables.append(v)
39
40 def getVariables(self):
41 return self.variables
42
43 Variables = property(getVariables)
44
45 def getFunctions(self):
46 return self.funcs
47
48 Functions = property(getFunctions)
49
50 def findFunction(self, name):
51 for f in self.funcs:
52 if f.name == name:
53 return f
54 raise KeyError(name)
55
56 getFunction = findFunction
57
58 def dump(self, indent=' '):
59 print(self)
60 for v in self.Variables:
61 print(indent, v)
62 for fn in self.Functions:
63 fn.dump(indent=indent+' ')
64
65 # Analysis functions:
66 def check(self):
67 """ Perform sanity check on module """
68 for f in self.Functions:
69 f.check()
70
71
72 class Function:
73 """
74 Function definition. Contains an entry block.
75 """
76 def __init__(self, name):
77 self.name = name
78 self.entry = Block('{}_entry'.format(name))
79 self.epiloog = Block('{}_epilog'.format(name))
80 self.epiloog.addInstruction(Terminator())
81 self.return_value = Temp('{}_retval'.format(name))
82 self.arguments = []
83 self.localvars = []
84
85 def __repr__(self):
86 args = ','.join(str(a) for a in self.arguments)
87 return 'Function {}({})'.format(self.name, args)
88
89 def addBB(self, bb):
90 self.bbs.append(bb)
91 bb.parent = self
92 addBlock = addBB
93
94 def removeBasicBlock(self, bb):
95 self.bbs.remove(bb)
96 bb.parent = None
97
98 def getBBs(self):
99 bbs = [self.entry]
100 worklist = [self.entry]
101 while worklist:
102 b = worklist.pop()
103 for sb in b.Successors:
104 if sb not in bbs:
105 bbs.append(sb)
106 worklist.append(sb)
107 bbs.remove(self.entry)
108 if self.epiloog in bbs:
109 bbs.remove(self.epiloog)
110 bbs.insert(0, self.entry)
111 bbs.append(self.epiloog)
112 return bbs
113
114 def findBasicBlock(self, name):
115 for bb in self.bbs:
116 if bb.name == name:
117 return bb
118 raise KeyError(name)
119
120 Blocks = property(getBBs)
121
122 @property
123 def Entry(self):
124 return self.entry
125
126 def check(self):
127 for b in self.Blocks:
128 b.check()
129
130 def addParameter(self, p):
131 assert type(p) is Parameter
132 p.num = len(self.arguments)
133 self.arguments.append(p)
134
135 def addLocal(self, l):
136 assert type(l) is LocalVariable
137 self.localvars.append(l)
138
139 def dump(self, indent=''):
140 print(indent+str(self))
141 for bb in self.Blocks:
142 print(indent+' '+str(bb))
143 for ins in bb.Instructions:
144 print(indent +' '*2 + str(ins))
145
146
147 class Block:
148 """
149 Uninterrupted sequence of instructions with a label at the start.
150 """
151 def __init__(self, name):
152 self.name = name
153 self.instructions = []
154
155 def __repr__(self):
156 return 'Block {0}'.format(self.name)
157
158 def addInstruction(self, i):
159 i.parent = self
160 assert not isinstance(self.LastInstruction, LastStatement)
161 self.instructions.append(i)
162
163 def replaceInstruction(self, i1, i2):
164 idx = self.instructions.index(i1)
165 i1.parent = None
166 i1.delete()
167 i2.parent = self
168 self.instructions[idx] = i2
169
170 def removeInstruction(self, i):
171 i.parent = None
172 i.delete()
173 self.instructions.remove(i)
174
175 def getInstructions(self):
176 return self.instructions
177 Instructions = property(getInstructions)
178
179 def getLastIns(self):
180 if not self.Empty:
181 return self.instructions[-1]
182 LastInstruction = property(getLastIns)
183
184 @property
185 def Empty(self):
186 return len(self.instructions) == 0
187
188 @property
189 def FirstInstruction(self):
190 return self.instructions[0]
191
192 def getSuccessors(self):
193 if not self.Empty:
194 return self.LastInstruction.Targets
195 return []
196 Successors = property(getSuccessors)
197
198 def getPredecessors(self):
199 preds = []
200 for bb in self.parent.BasicBlocks:
201 if self in bb.Successors:
202 preds.append(bb)
203 return preds
204 Predecessors = property(getPredecessors)
205
206 def precedes(self, other):
207 raise NotImplementedError()
208
209 def check(self):
210 assert isinstance(self.LastInstruction, LastStatement)
211 for i in self.instructions[:-1]:
212 assert not isinstance(i, LastStatement)
213
214
215 # Instructions:
216 class Term:
217 def __init__(self, x):
218 self.x = x
219
220 def match_tree(tree, pattern):
221 if type(pattern) is Term:
222 return True, {pattern: tree}
223 elif type(pattern) is Binop and type(tree) is Binop and tree.operation == pattern.operation:
224 res_a, mp_a = match_tree(tree.a, pattern.a)
225 res_b, mp_b = match_tree(tree.b, pattern.b)
226 assert not (mp_a.keys() & mp_b.keys())
227 mp_a.update(mp_b)
228 return res_a and res_b, mp_a
229 elif type(pattern) is Const and type(tree) is Const and pattern.value == tree.value:
230 return True, {}
231 else:
232 return False, {}
233
234
235 class Expression:
236 pass
237
238
239 class Const(Expression):
240 def __init__(self, value):
241 self.value = value
242
243 def __repr__(self):
244 return 'Const {}'.format(self.value)
245
246
247 # Function calling:
248 class Call(Expression):
249 def __init__(self, f, arguments):
250 self.f = f
251 assert type(f) is Function
252 self.arguments = arguments
253
254 def __repr__(self):
255 args = ', '.join([str(arg) for arg in self.arguments])
256 return '{}({})'.format(self.f.name, args)
257
258
259 # Data operations
260 class Binop(Expression):
261 ops = ['+', '-', '*', '/', '|', '&', '<<', '>>']
262 def __init__(self, value1, operation, value2):
263 assert operation in Binop.ops
264 self.a = value1
265 self.b = value2
266 self.operation = operation
267
268 def __repr__(self):
269 a, b = self.a, self.b
270 return '({} {} {})'.format(a, self.operation, b)
271
272
273 def Add(a, b):
274 """ Convenience call """
275 return Binop(a, '+', b)
276
277
278 class Eseq(Expression):
279 """ Sequence of instructions where the last is an expression """
280 def __init__(self, stmt, e):
281 self.stmt = stmt
282 self.e = e
283
284 def __repr__(self):
285 return '({}, {})'.format(self.stmt, self.e)
286
287
288 class Alloc(Expression):
289 """ Allocates space on the stack """
290 def __init__(self):
291 super().__init__()
292
293 def __repr__(self):
294 return 'Alloc'
295
296
297 class Variable(Expression):
298 def __init__(self, name):
299 self.name = name
300
301 def __repr__(self):
302 return 'Var {}'.format(self.name)
303
304
305 class LocalVariable(Variable):
306 def __repr__(self):
307 return 'Local {}'.format(self.name)
308
309
310 class Parameter(Variable):
311 def __repr__(self):
312 return 'Param {}'.format(self.name)
313
314
315 class Temp(Expression):
316 """ Temporary storage, same as register """
317 def __init__(self, name):
318 self.name = name
319
320 def __repr__(self):
321 return 'TMP_{}'.format(self.name)
322
323
324 class Mem(Expression):
325 def __init__(self, e):
326 self.e = e
327
328 def __repr__(self):
329 return '[{}]'.format(self.e)
330
331
332 class Statement:
333 """ Base class for all instructions. """
334 pass
335
336
337 class Move(Statement):
338 def __init__(self, dst, src):
339 self.dst = dst
340 self.src = src
341
342 def __repr__(self):
343 return '{} = {}'.format(self.dst, self.src)
344
345
346 class Exp(Statement):
347 def __init__(self, e):
348 self.e = e
349
350 def __repr__(self):
351 return '{}'.format(self.e)
352
353
354 class Label(Statement):
355 # TODO: is this duplicate with block?
356 def __init__(self, name):
357 self.name = name
358 self.statements = []
359
360 def __repr__(self):
361 return 'LABEL {}:'.format(self.name)
362
363
364 # Branching:
365 class LastStatement(Statement):
366 pass
367
368
369 class Terminator(LastStatement):
370 """ Instruction that terminates the terminal block """
371 Targets = []
372 def __repr__(self):
373 return 'Terminator'
374
375
376 class Jump(LastStatement):
377 def __init__(self, target):
378 self.target = target
379 self.Targets = [target]
380
381 def __repr__(self):
382 return 'BRANCH {}'.format(self.target.name)
383
384
385 class CJump(LastStatement):
386 conditions = ['==', '<', '>', '>=', '<=', '!=']
387 def __init__(self, a, cond, b, lab_yes, lab_no):
388 assert cond in CJump.conditions
389 self.a = a
390 self.cond = cond
391 self.b = b
392 self.lab_yes = lab_yes
393 self.lab_no = lab_no
394 self.Targets = [lab_yes, lab_no]
395
396 def __repr__(self):
397 return 'IF {} {} {} THEN {} ELSE {}'.format(self.a, self.cond, self.b, self.lab_yes, self.lab_no)
398
399
400 class NamedClassGenerator:
401 def __init__(self, prefix, cls):
402 self.prefix = prefix
403 self.cls = cls
404 def NumGen():
405 a = 0
406 while True:
407 yield a
408 a = a + 1
409 self.nums = NumGen()
410
411 def gen(self, prefix=None):
412 if not prefix:
413 prefix = self.prefix
414 return self.cls('{0}{1}'.format(prefix, self.nums.__next__()))
415
416
417 class Builder:
418 """ Base class for ir code generators """
419 def __init__(self):
420 self.prepare()
421
422 def prepare(self):
423 self.newTemp = NamedClassGenerator('reg', Temp).gen
424 self.newBlock = NamedClassGenerator('block', Block).gen
425 self.bb = None
426 self.m = None
427 self.fn = None
428 self.loc = None
429
430 # Helpers:
431 def setModule(self, m):
432 self.m = m
433
434 def newFunction(self, name):
435 f = Function(name)
436 self.m.addFunc(f)
437 return f
438
439 def setFunction(self, f):
440 self.fn = f
441 self.bb = f.entry if f else None
442
443 def setBlock(self, b):
444 self.bb = b
445
446 def setLoc(self, l):
447 self.loc = l
448
449 def emit(self, i):
450 assert isinstance(i, Statement)
451 i.debugLoc = self.loc
452 if not self.bb:
453 raise Exception('No basic block')
454 self.bb.addInstruction(i)
455
456