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