269
|
1
|
|
2 import ir
|
|
3 import irmach
|
275
|
4 from irmach import makeIns
|
269
|
5
|
|
6 def genTemps():
|
|
7 n = 900
|
|
8 while True:
|
275
|
9 yield ir.Temp('t{}'.format(n))
|
269
|
10 n = n + 1
|
|
11
|
|
12 class InstructionSelector:
|
|
13 """
|
|
14 Base instruction selector. This class must be overridden by
|
|
15 backends.
|
|
16 """
|
275
|
17 def __init__(self):
|
|
18 self.temps = genTemps()
|
|
19
|
269
|
20 def newTmp(self):
|
|
21 return self.temps.__next__()
|
|
22
|
275
|
23 def munchFunction(self, f, frame):
|
269
|
24 # Entry point for instruction selection
|
275
|
25 assert isinstance(f, ir.Function)
|
269
|
26 self.targets = {}
|
275
|
27 # Enter a frame per function:
|
|
28 self.frame = frame
|
|
29 # First define labels:
|
|
30 for bb in f.Blocks:
|
|
31 itgt = makeIns('{}:'.format(bb.name))
|
|
32 self.targets[bb] = itgt
|
|
33 # Generate code for all blocks:
|
|
34 for bb in f.Blocks:
|
|
35 self.emit2(self.targets[bb])
|
|
36 for i in bb.Instructions:
|
|
37 self.munchStm(i)
|
|
38 self.munchStm(ir.Move(self.frame.rv, f.return_value))
|
|
39 self.emit('mov %s0, %s0', src=[self.frame.rv])
|
269
|
40
|
275
|
41 def move(self, dst, src):
|
|
42 self.emit('mov %d0, %s0', src=[src], dst=[dst])
|
269
|
43
|
|
44 def emit(self, *args, **kwargs):
|
|
45 """ Abstract instruction emitter """
|
275
|
46 i = makeIns(*args, **kwargs)
|
269
|
47 return self.emit2(i)
|
|
48
|
|
49 def emit2(self, i):
|
274
|
50 self.frame.instructions.append(i)
|
269
|
51 return i
|
|
52
|
|
53 def munchStm(self, s):
|
274
|
54 """ Implement this in the target specific back-end """
|
269
|
55 raise NotImplementedError()
|
|
56
|
|
57 def munchExpr(self, e):
|
274
|
58 """ Implement this in the target specific back-end """
|
269
|
59 raise NotImplementedError()
|
|
60
|