comparison python/c3/codegenerator.py @ 171:3eb9b9e2958d

Improved IR code
author Windel Bouwman
date Wed, 03 Apr 2013 22:20:20 +0200
parents 4348da5ca307
children 5a7d37d615ee
comparison
equal deleted inserted replaced
170:4348da5ca307 171:3eb9b9e2958d
1 import ir 1 import ir
2 from . import astnodes 2 from . import astnodes
3 3 from .scope import boolType
4 def NumGen(): 4
5 a = 0
6 while True:
7 yield a
8 a = a + 1
9
10 class NameGenerator:
11 def __init__(self, prefix):
12 self.prefix = prefix
13 self.nums = NumGen()
14 def gen(self):
15 return '{0}{1}'.format(self.prefix, self.nums.__next__())
16
17 class CodeGenerator: 5 class CodeGenerator:
18 """ Generates intermediate code from a package """ 6 """ Generates intermediate code from a package """
19 def gencode(self, pkg): 7 def gencode(self, pkg):
20 assert type(pkg) is astnodes.Package 8 assert type(pkg) is astnodes.Package
21 self.m = ir.Module(pkg.name) 9 self.builder = ir.Builder()
22 self.newTmp = NameGenerator('t').gen 10 m = ir.Module(pkg.name)
23 self.newLab = NameGenerator('lab').gen 11 self.builder.setModule(m)
24 self.genModule(pkg) 12 self.genModule(pkg)
25 return self.m 13 return m
26 14
27 # Helpers:
28 def addIns(self, i):
29 self.m.Instructions.append(i)
30 # inner helpers: 15 # inner helpers:
31 def genModule(self, pkg): 16 def genModule(self, pkg):
32 for s in pkg.scope: 17 for s in pkg.scope:
33 if type(s) is astnodes.Variable: 18 if type(s) is astnodes.Variable:
34 # TODO 19 # TODO
35 pass 20 pass
36 elif type(s) is astnodes.Function: 21 elif type(s) is astnodes.Function:
37 # TODO: handle arguments 22 # TODO: handle arguments
38 # TODO handle return? 23 # TODO handle return?
39 self.addIns(ir.LabelInstruction(s.name)) 24 bb = self.builder.newBB()
25 self.builder.setBB(bb)
40 self.genCode(s.body) 26 self.genCode(s.body)
41 self.addIns(ir.RetInstruction()) 27 self.builder.addIns(ir.Return())
42 else: 28 else:
43 print(s) 29 print(s)
44 30
45 def genCode(self, code): 31 def genCode(self, code):
46 if type(code) is astnodes.CompoundStatement: 32 if type(code) is astnodes.CompoundStatement:
47 for s in code.statements: 33 for s in code.statements:
48 self.genCode(s) 34 self.genCode(s)
49 elif type(code) is astnodes.Assignment: 35 elif type(code) is astnodes.Assignment:
50 re = self.genExprCode(code.rval) 36 re = self.genExprCode(code.rval)
51 self.addIns(ir.StoreInstruction(code.lval, re)) 37 self.builder.addIns(ir.Store(code.lval, re))
52 elif type(code) is astnodes.IfStatement: 38 elif type(code) is astnodes.IfStatement:
53 cr = self.genExprCode(code.condition) 39 bbtrue = self.builder.newBB()
54 t1, t2, te = self.newLab(), self.newLab(), self.newLab() 40 bbfalse = self.builder.newBB()
55 self.addIns(ir.IfInstruction(cr, t1, t2)) 41 te = self.builder.newBB()
56 self.addIns(ir.LabelInstruction(t1)) 42 self.genCondCode(code.condition, bbtrue, bbfalse)
43 self.builder.setBB(bbtrue)
57 self.genCode(code.truestatement) 44 self.genCode(code.truestatement)
58 self.addIns(ir.BranchInstruction(te)) 45 self.builder.addIns(ir.Branch(te))
59 self.addIns(ir.LabelInstruction(t2)) 46 self.builder.setBB(bbfalse)
60 self.genCode(code.falsestatement) 47 self.genCode(code.falsestatement)
61 self.addIns(ir.LabelInstruction(te)) 48 self.builder.addIns(ir.Branch(te))
49 self.builder.setBB(te)
62 elif type(code) is astnodes.FunctionCall: 50 elif type(code) is astnodes.FunctionCall:
63 pass 51 pass
64 elif type(code) is astnodes.EmptyStatement: 52 elif type(code) is astnodes.EmptyStatement:
65 pass 53 pass
66 elif type(code) is astnodes.ReturnStatement: 54 elif type(code) is astnodes.ReturnStatement:
67 pass 55 pass
68 else: 56 else:
69 print('Unknown stmt:', code) 57 print('Unknown stmt:', code)
70 58 def genCondCode(self, expr, bbtrue, bbfalse):
59 # Implement sequential logical operators
60 assert expr.typ == boolType
61 if type(expr) is astnodes.Binop:
62 if expr.op == 'or':
63 l2 = self.builder.newBB()
64 self.genCondCode(expr.a, bbtrue, l2)
65 self.builder.setBB(l2)
66 self.genCondCode(expr.b, bbtrue, bbfalse)
67 elif expr.op == 'and':
68 l2 = self.builder.newBB()
69 self.genCondCode(expr.a, l2, bbfalse)
70 self.builder.setBB(l2)
71 self.genCondCode(expr.b, bbtrue, bbfalse)
72 elif expr.op in ['==', '>', '<']:
73 ta = self.genExprCode(expr.a)
74 tb = self.genExprCode(expr.b)
75 i = ir.ConditionalBranch(ta, expr.op, tb, bbtrue, bbfalse)
76 self.builder.addIns(i)
77 else:
78 raise NotImlementedError()
79 print('Unknown cond', expr)
80 elif type(expr) is astnodes.Literal:
81 if expr.val:
82 self.builder.addIns(ir.BranchInstruction(bbtrue))
83 else:
84 self.builder.addIns(ir.BranchInstruction(bbfalse))
85 else:
86 print('Unknown cond', expr)
71 def genExprCode(self, expr): 87 def genExprCode(self, expr):
72 if type(expr) is astnodes.Binop: 88 if type(expr) is astnodes.Binop:
73 ra = self.genExprCode(expr.a) 89 ra = self.genExprCode(expr.a)
74 rb = self.genExprCode(expr.b) 90 rb = self.genExprCode(expr.b)
91 tmp = self.builder.newTmp()
75 ops = ['+', '-', '*', '/', 'and', 'or'] 92 ops = ['+', '-', '*', '/', 'and', 'or']
76 if expr.op in ops: 93 if expr.op in ops:
77 op = expr.op 94 op = expr.op
78 tmp = self.newTmp()
79 ins = ir.BinaryOperator(tmp, op, ra, rb) 95 ins = ir.BinaryOperator(tmp, op, ra, rb)
80 self.addIns(ins) 96 self.builder.addIns(ins)
81 return tmp 97 return tmp
82 else: 98 else:
83 print('Unknown binop {0}'.format(expr)) 99 print('Unknown {0}'.format(expr))
100 # TODO
101 return tmp
84 elif type(expr) is astnodes.Constant: 102 elif type(expr) is astnodes.Constant:
85 tmp = unique() 103 tmp = self.builder.newTmp()
104 # TODO
105 return tmp
86 elif type(expr) is astnodes.VariableUse: 106 elif type(expr) is astnodes.VariableUse:
87 tmp = self.newTmp() 107 tmp = self.builder.newTmp()
108 i = ir.Load(expr, tmp)
109 self.builder.addIns(i)
110 return tmp
88 elif type(expr) is astnodes.Literal: 111 elif type(expr) is astnodes.Literal:
89 tmp = self.newTmp() 112 tmp = self.builder.newTmp()
90 ins = ir.MoveInstruction(tmp, expr.val) 113 ins = ir.ImmLoad(tmp, expr.val)
91 self.addIns(ins) 114 self.builder.addIns(ins)
92 return tmp 115 return tmp
93 else: 116 else:
94 print('Unknown expr:', code) 117 print('Unknown expr:', code)
95 118