290
|
1 import ir
|
292
|
2 from target import Target
|
210
|
3 from ppci import CompilerError
|
290
|
4 import transform
|
|
5 import canon
|
292
|
6 import registerallocator
|
210
|
7
|
290
|
8
|
210
|
9 class CodeGenerator:
|
292
|
10 """ Generic code generator """
|
|
11 def __init__(self, target):
|
290
|
12 # TODO: schedule traces in better order.
|
|
13 # This is optional!
|
292
|
14 assert isinstance(target, Target), target
|
290
|
15 self.target = target
|
292
|
16 self.ins_sel = target.ins_sel
|
290
|
17 self.ra = registerallocator.RegisterAllocator()
|
|
18
|
292
|
19 def generateFunc(self, irfunc, outs):
|
290
|
20 """ Generate code for one function into a frame """
|
|
21 # Cleanup function:
|
|
22 transform.removeEmptyBlocks(irfunc)
|
|
23
|
|
24 # Create a frame for this function:
|
292
|
25 frame = self.target.FrameClass(irfunc.name)
|
210
|
26
|
290
|
27 # Canonicalize the intermediate language:
|
|
28 canon.make(irfunc, frame)
|
|
29 self.ins_sel.munchFunction(irfunc, frame)
|
210
|
30
|
290
|
31 # Do register allocation:
|
|
32 self.ra.allocFrame(frame)
|
|
33 # TODO: Peep-hole here?
|
|
34
|
|
35 # Add label and return and stack adjustment:
|
|
36 frame.EntryExitGlue3()
|
|
37
|
|
38 # Materialize assembly
|
|
39 # Materialize the register allocated instructions into a stream of
|
|
40 # real instructions.
|
292
|
41 frame.lower_to(outs)
|
290
|
42 return frame
|
|
43
|
292
|
44 def generate(self, ircode, outs):
|
210
|
45 assert isinstance(ircode, ir.Module)
|
292
|
46 outs.selectSection('code')
|
210
|
47
|
290
|
48 # Munch program into a bunch of frames. One frame per function.
|
|
49 # Each frame has a flat list of abstract instructions.
|
|
50 # Generate code for all functions:
|
292
|
51 self.frames = [self.generateFunc(func, outs) for func in ircode.Functions]
|
290
|
52 return self.frames
|