290
|
1 import ir
|
|
2 import target
|
210
|
3 from ppci import CompilerError
|
290
|
4 import transform
|
|
5 import canon
|
210
|
6
|
290
|
7
|
|
8 # TODO: this class could be target independent:
|
210
|
9 class CodeGenerator:
|
290
|
10 def __init__(self, outs, target):
|
|
11 # TODO: schedule traces in better order.
|
|
12 # This is optional!
|
210
|
13 assert isinstance(tg, target.Target)
|
290
|
14 self.target = target
|
|
15 self.ins_sel = ArmInstructionSelector()
|
|
16 self.ra = registerallocator.RegisterAllocator()
|
|
17 self.outs = outs
|
|
18 self.outs.getSection('code').address = 0x08000000
|
|
19 self.outs.getSection('data').address = 0x20000000
|
|
20
|
|
21 def generateFunc(self, irfunc):
|
|
22 """ Generate code for one function into a frame """
|
|
23 # Cleanup function:
|
|
24 transform.removeEmptyBlocks(irfunc)
|
|
25
|
|
26 # Create a frame for this function:
|
|
27 frame = ArmFrame(irfunc.name)
|
210
|
28
|
290
|
29 # Canonicalize the intermediate language:
|
|
30 canon.make(irfunc, frame)
|
|
31 self.ins_sel.munchFunction(irfunc, frame)
|
210
|
32
|
290
|
33 # Do register allocation:
|
|
34 self.ra.allocFrame(frame)
|
|
35 # TODO: Peep-hole here?
|
|
36
|
|
37 # Can we materialize here??
|
|
38
|
|
39 # Add label and return and stack adjustment:
|
|
40 frame.EntryExitGlue3()
|
|
41
|
|
42 # Materialize assembly
|
|
43 # Materialize the register allocated instructions into a stream of
|
|
44 # real instructions.
|
|
45 frame.lower_to(self.outs)
|
|
46 return frame
|
|
47
|
210
|
48 def generate(self, ircode):
|
|
49 assert isinstance(ircode, ir.Module)
|
290
|
50 self.outs.selectSection('code')
|
|
51 # assembly glue to make it work:
|
|
52 # TODO: this must be in source code, not in compiler
|
|
53 self.outs.emit(arm.dcd_ins(Imm32(0x20000678))) # initial SP
|
|
54 self.outs.emit(arm.dcd_ins(Imm32(0x08000009))) # reset vector
|
|
55 self.outs.emit(arm.b_ins(LabelRef('main')))
|
210
|
56
|
290
|
57 # Munch program into a bunch of frames. One frame per function.
|
|
58 # Each frame has a flat list of abstract instructions.
|
|
59 # Generate code for all functions:
|
|
60 self.frames = [self.generateFunc(func) for func in ircode.Functions]
|
|
61
|
|
62 # TODO: fixup references, do this in another way?
|
|
63 self.outs.backpatch()
|
|
64 self.outs.backpatch() # Why two times?
|
|
65 return self.frames
|