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