comparison python/c3/codegenerator.py @ 268:5ec7580976d9

Op naar tree-IR
author Windel Bouwman
date Wed, 14 Aug 2013 20:12:40 +0200
parents 444b9df2ed99
children 5f8c04a8d26b
comparison
equal deleted inserted replaced
267:e7c8f7eb3f59 268:5ec7580976d9
3 from . import astnodes 3 from . import astnodes
4 from .scope import boolType, intType 4 from .scope import boolType, intType
5 from ppci import CompilerError 5 from ppci import CompilerError
6 from .typecheck import theType 6 from .typecheck import theType
7 7
8 tmpnames = {'+':'add', '-':'sub', '*': 'mul', '/':'div', '|':'or', \
9 '&':'and', '>>':'shl', '<<':'shr'}
10 8
11 class CodeGenerator: 9 class CodeGenerator(ir.Builder):
12 """ Generates intermediate code from a package """ 10 """ Generates intermediate code from a package """
13 def __init__(self): 11 def __init__(self):
14 self.logger = logging.getLogger('c3cgen') 12 self.logger = logging.getLogger('c3cgen')
15 13
16 def gencode(self, pkg): 14 def gencode(self, pkg):
15 self.prepare()
17 assert type(pkg) is astnodes.Package 16 assert type(pkg) is astnodes.Package
18 self.logger.info('Generating ir-code for {}'.format(pkg.name)) 17 self.logger.info('Generating ir-code for {}'.format(pkg.name))
19 self.varMap = {} # Maps variables to storage locations. 18 self.varMap = {} # Maps variables to storage locations.
20 self.funcMap = {} 19 self.funcMap = {}
21 self.builder = ir.Builder() 20 self.m = ir.Module(pkg.name)
22 m = ir.Module(pkg.name)
23 self.builder.setModule(m)
24 self.genModule(pkg) 21 self.genModule(pkg)
25 return m 22 return self.m
26 23
27 # inner helpers: 24 # inner helpers:
28 def genModule(self, pkg): 25 def genModule(self, pkg):
29 # Take care of forward declarations: 26 # Take care of forward declarations:
30 for s in pkg.innerScope.Functions: 27 for s in pkg.innerScope.Functions:
31 f = self.builder.newFunction(s.name) 28 f = self.newFunction(s.name)
32 self.funcMap[s] = f 29 self.funcMap[s] = f
33 for s in pkg.innerScope: 30 for s in pkg.innerScope:
34 if type(s) is astnodes.Variable: 31 if type(s) is astnodes.Variable:
35 v = self.builder.newTmp(s.name) 32 #v = self.builder.newTmp(s.name)
36 #self.builder.addIns(ir.Alloc(v)) 33 self.varMap[s] = self.newTemp()
37 self.varMap[s] = v 34 pass
38 elif type(s) is astnodes.Function: 35 elif type(s) is astnodes.Function:
39 # TODO: handle arguments 36 self.genFunction(s)
40 f = self.funcMap[s] 37 else:
41 self.builder.setFunction(f) 38 raise NotImplementedError(str(s))
42 bb = self.builder.newBB()
43 f.entry = bb
44 self.builder.setBB(bb)
45 # generate room for locals:
46 39
47 for sym in s.innerScope: 40 def genFunction(self, fn):
48 #print(sym, sym.isParameter) 41 # TODO: handle arguments
49 # TODO: handle parameters different 42 f = self.funcMap[fn]
50 v = self.builder.newTmp(sym.name) 43 self.setFunction(f)
51 self.builder.addIns(ir.Alloc(v)) 44 # generate room for locals:
52 self.varMap[sym] = v
53 45
54 self.genCode(s.body) 46 for sym in fn.innerScope:
55 # TODO handle return? 47 # TODO: handle parameters different
56 self.builder.addIns(ir.Return()) 48 v = self.newTemp()
57 self.builder.setFunction(None) 49 # TODO: make this ssa here??
58 else: 50 self.varMap[sym] = v
59 print(s) 51
52 self.genCode(fn.body)
53 # TODO handle return?
54 self.emit(ir.Return(ir.Const(0)))
55 self.setFunction(None)
60 56
61 def genCode(self, code): 57 def genCode(self, code):
62 assert isinstance(code, astnodes.Statement) 58 assert isinstance(code, astnodes.Statement)
63 self.builder.setLoc(code.loc) 59 self.setLoc(code.loc)
64 if type(code) is astnodes.CompoundStatement: 60 if type(code) is astnodes.CompoundStatement:
65 for s in code.statements: 61 for s in code.statements:
66 self.genCode(s) 62 self.genCode(s)
67 elif type(code) is astnodes.Assignment: 63 elif type(code) is astnodes.Assignment:
68 re = self.genExprCode(code.rval) 64 rval = self.genExprCode(code.rval)
69 loc = self.genExprCode(code.lval) 65 lval = self.genExprCode(code.lval)
70 self.builder.addIns(ir.Store(loc, re)) 66 self.emit(ir.Move(lval, rval))
71 elif type(code) is astnodes.ExpressionStatement: 67 elif type(code) is astnodes.ExpressionStatement:
72 self.genExprCode(code.ex) 68 self.genExprCode(code.ex)
73 elif type(code) is astnodes.IfStatement: 69 elif type(code) is astnodes.IfStatement:
74 bbtrue = self.builder.newBB() 70 bbtrue = self.newBlock()
75 bbfalse = self.builder.newBB() 71 bbfalse = self.newBlock()
76 te = self.builder.newBB() 72 te = self.newBlock()
77 self.genCondCode(code.condition, bbtrue, bbfalse) 73 self.genCondCode(code.condition, bbtrue, bbfalse)
78 self.builder.setBB(bbtrue) 74 self.setBlock(bbtrue)
79 self.genCode(code.truestatement) 75 self.genCode(code.truestatement)
80 self.builder.addIns(ir.Branch(te)) 76 self.emit(ir.Jump(te))
81 self.builder.setBB(bbfalse) 77 self.setBlock(bbfalse)
82 if code.falsestatement: 78 if code.falsestatement:
83 self.genCode(code.falsestatement) 79 self.genCode(code.falsestatement)
84 self.builder.addIns(ir.Branch(te)) 80 self.emit(ir.Jump(te))
85 self.builder.setBB(te) 81 self.setBlock(te)
86 elif type(code) is astnodes.ReturnStatement: 82 elif type(code) is astnodes.ReturnStatement:
87 if code.expr: 83 if code.expr:
88 re = self.genExprCode(code.expr) 84 re = self.genExprCode(code.expr)
89 self.builder.addIns(ir.Return(re)) 85 self.emit(ir.Return(re))
90 else: 86 else:
91 self.builder.addIns(ir.Return()) 87 self.builder.addIns(ir.Return())
92 elif type(code) is astnodes.WhileStatement: 88 elif type(code) is astnodes.WhileStatement:
93 bbdo = self.builder.newBB() 89 bbdo = self.newBlock()
94 bbtest = self.builder.newBB() 90 bbtest = self.newBlock()
95 te = self.builder.newBB() 91 te = self.newBlock()
96 self.builder.addIns(ir.Branch(bbtest)) 92 self.emit(ir.Jump(bbtest))
97 self.builder.setBB(bbtest) 93 self.setBlock(bbtest)
98 self.genCondCode(code.condition, bbdo, te) 94 self.genCondCode(code.condition, bbdo, te)
99 self.builder.setBB(bbdo) 95 self.setBlock(bbdo)
100 self.genCode(code.statement) 96 self.genCode(code.statement)
101 self.builder.addIns(ir.Branch(bbtest)) 97 self.emit(ir.Jump(bbtest))
102 self.builder.setBB(te) 98 self.setBlock(te)
103 else: 99 else:
104 print('Unknown stmt:', code) 100 raise NotImplementedError('Unknown stmt {}'.format(code))
105 raise NotImplementedError()
106 101
107 def genCondCode(self, expr, bbtrue, bbfalse): 102 def genCondCode(self, expr, bbtrue, bbfalse):
108 # Implement sequential logical operators 103 # Implement sequential logical operators
109 assert expr.typ == boolType 104 assert expr.typ == boolType
110 if type(expr) is astnodes.Binop: 105 if type(expr) is astnodes.Binop:
111 if expr.op == 'or': 106 if expr.op == 'or':
112 l2 = self.builder.newBB() 107 l2 = self.newBlock()
113 self.genCondCode(expr.a, bbtrue, l2) 108 self.genCondCode(expr.a, bbtrue, l2)
114 self.builder.setBB(l2) 109 self.setBlock(l2)
115 self.genCondCode(expr.b, bbtrue, bbfalse) 110 self.genCondCode(expr.b, bbtrue, bbfalse)
116 elif expr.op == 'and': 111 elif expr.op == 'and':
117 l2 = self.builder.newBB() 112 l2 = self.newBlock()
118 self.genCondCode(expr.a, l2, bbfalse) 113 self.genCondCode(expr.a, l2, bbfalse)
119 self.builder.setBB(l2) 114 self.setBlock(l2)
120 self.genCondCode(expr.b, bbtrue, bbfalse) 115 self.genCondCode(expr.b, bbtrue, bbfalse)
121 elif expr.op in ['==', '>', '<']: 116 elif expr.op in ['==', '>', '<']:
122 ta = self.genExprCode(expr.a) 117 ta = self.genExprCode(expr.a)
123 tb = self.genExprCode(expr.b) 118 tb = self.genExprCode(expr.b)
124 i = ir.ConditionalBranch(ta, expr.op, tb, bbtrue, bbfalse) 119 self.emit(ir.CJump(ta, expr.op, tb, bbtrue, bbfalse))
125 self.builder.addIns(i) 120 else:
126 else: 121 raise NotImplementedError('Unknown condition {}'.format(expr))
127 raise NotImlementedError('Unknown condition {0}'.format(expr))
128 elif type(expr) is astnodes.Literal: 122 elif type(expr) is astnodes.Literal:
129 if expr.val: 123 if expr.val:
130 self.builder.addIns(ir.Branch(bbtrue)) 124 self.emit(ir.Jump(bbtrue))
131 else: 125 else:
132 self.builder.addIns(ir.Branch(bbfalse)) 126 self.emit(ir.Jump(bbfalse))
133 else: 127 else:
134 print('Unknown cond', expr) 128 raise NotImplementedError('Unknown cond {}'.format(expr))
135 raise NotImplementedError()
136
137 def cast_to_rvalue(self, expr, loc):
138 """ Cast lvalue to rvalue if required """
139 if hasattr(expr, 'expect_rvalue'):
140 # Load value from memory location:
141 tmp = self.builder.newTmp()
142 i = ir.Load(loc, tmp)
143 self.builder.addIns(i)
144 return tmp
145 if expr.lvalue:
146 return loc
147 129
148 def genExprCode(self, expr): 130 def genExprCode(self, expr):
149 assert isinstance(expr, astnodes.Expression) 131 assert isinstance(expr, astnodes.Expression)
150 if type(expr) is astnodes.Binop: 132 if type(expr) is astnodes.Binop and expr.op in ir.Binop.ops:
151 ra = self.genExprCode(expr.a)
152 rb = self.genExprCode(expr.b)
153 ops = ['+', '-', '*', '/', '|', '&', '<<', '>>']
154 if expr.op in ops:
155 tmp = self.builder.newTmp(tmpnames[expr.op])
156 op = expr.op
157 ins = ir.BinaryOperator(tmp, op, ra, rb)
158 self.builder.addIns(ins)
159 return tmp
160 else:
161 raise NotImplementedError('Unknown {0}'.format(expr))
162 tmp = self.builder.newTmp()
163 # TODO
164 return tmp
165 elif type(expr) is astnodes.Unop:
166 ra = self.genExprCode(expr.a) 133 ra = self.genExprCode(expr.a)
167 if expr.op == '&': 134 rb = self.genExprCode(expr.b)
168 # Address of operator 135 return ir.Binop(ra, expr.op, rb)
169 tmp = self.builder.newTmp('addr') 136 elif type(expr) is astnodes.Unop and expr.op == '&':
170 return tmp 137 ra = self.genExprCode(expr.a)
171 #self.builder.addIns(ins) 138 # TODO: Make this work?
172 else: 139 return ra
173 raise NotImplementedError('Unknown {0}'.format(expr))
174 elif type(expr) is astnodes.Constant:
175 tmp = self.builder.newTmp()
176 # TODO
177 return tmp
178 elif type(expr) is astnodes.VariableUse: 140 elif type(expr) is astnodes.VariableUse:
179 loc = self.varMap[expr.target] 141 return self.varMap[expr.target]
180 return self.cast_to_rvalue(expr, loc)
181 elif type(expr) is astnodes.Deref: 142 elif type(expr) is astnodes.Deref:
182 # dereference pointer type: 143 # dereference pointer type:
183 addr = self.genExprCode(expr.ptr) 144 addr = self.genExprCode(expr.ptr)
184 tmp = self.builder.newTmp('deref') 145 return ir.Mem(addr)
185 ins = ir.Load(addr, tmp)
186 self.builder.addIns(ins)
187 return tmp
188 elif type(expr) is astnodes.FieldRef: 146 elif type(expr) is astnodes.FieldRef:
189 b = self.genExprCode(expr.base) 147 b = self.genExprCode(expr.base)
190 offset = self.builder.newTmp('off_' + expr.field) 148 #b = b.e
191 bt = theType(expr.base.typ) 149 bt = theType(expr.base.typ)
192 ofs = bt.fieldOffset(expr.field) 150 offset = ir.Const(bt.fieldOffset(expr.field))
193 ins = ir.ImmLoad(offset, ofs) 151 return ir.Mem(ir.Binop(b, '+', offset))
194 self.builder.addIns(ins)
195 tmp2 = self.builder.newTmp('adr_' + expr.field)
196 ins = ir.BinaryOperator(tmp2, '+', b, offset)
197 self.builder.addIns(ins)
198 return self.cast_to_rvalue(expr, tmp2)
199 elif type(expr) is astnodes.Literal: 152 elif type(expr) is astnodes.Literal:
200 tmp = self.builder.newTmp('const') 153 return ir.Const(expr.val)
201 ins = ir.ImmLoad(tmp, expr.val)
202 self.builder.addIns(ins)
203 return tmp
204 elif type(expr) is astnodes.TypeCast: 154 elif type(expr) is astnodes.TypeCast:
155 # TODO: improve this mess:
205 ar = self.genExprCode(expr.a) 156 ar = self.genExprCode(expr.a)
206 tt = theType(expr.to_type) 157 tt = theType(expr.to_type)
207 if isinstance(tt, astnodes.PointerType): 158 if isinstance(tt, astnodes.PointerType):
208 if expr.a.typ is intType: 159 if expr.a.typ is intType:
209 return ar 160 return ar
212 else: 163 else:
213 raise Exception() 164 raise Exception()
214 else: 165 else:
215 raise NotImplementedError("not implemented") 166 raise NotImplementedError("not implemented")
216 elif type(expr) is astnodes.FunctionCall: 167 elif type(expr) is astnodes.FunctionCall:
217 tmp = self.builder.newTmp("res") 168 args = [self.genExprCode(e) for e in expr.args]
218 args = []
219 for arg in expr.args:
220 ar = self.genExprCode(arg)
221 args.append(ar)
222 fn = self.funcMap[expr.proc] 169 fn = self.funcMap[expr.proc]
223 ins = ir.Call(fn, args, tmp) 170 return ir.Call(fn, args)
224 self.builder.addIns(ins)
225 return tmp
226 else: 171 else:
227 raise NotImplementedError('Unknown expr {}'.format(expr)) 172 raise NotImplementedError('Unknown expr {}'.format(expr))
228 173