comparison python/c3/codegenerator.py @ 230:88a1e0baef65

Added some tests for IR-code
author Windel Bouwman
date Sat, 13 Jul 2013 19:53:44 +0200
parents 7f18ed9b6b7e
children 521567d17388
comparison
equal deleted inserted replaced
229:51d5ed1bd503 230:88a1e0baef65
1 import ir 1 import ir
2 from . import astnodes 2 from . import astnodes
3 from .scope import boolType, intType 3 from .scope import boolType, intType
4 from ppci import CompilerError 4 from ppci import CompilerError
5 from .typecheck import resolveType
6
7 tmpnames = {'+':'add', '-':'sub', '*': 'mul', '/':'div', '|':'or', '&':'and'}
5 8
6 class CodeGenerator: 9 class CodeGenerator:
7 """ Generates intermediate code from a package """ 10 """ Generates intermediate code from a package """
8 def gencode(self, pkg): 11 def gencode(self, pkg):
9 assert type(pkg) is astnodes.Package 12 assert type(pkg) is astnodes.Package
21 for s in pkg.innerScope.Functions: 24 for s in pkg.innerScope.Functions:
22 f = self.builder.newFunction(s.name) 25 f = self.builder.newFunction(s.name)
23 self.funcMap[s] = f 26 self.funcMap[s] = f
24 for s in pkg.innerScope: 27 for s in pkg.innerScope:
25 if type(s) is astnodes.Variable: 28 if type(s) is astnodes.Variable:
26 v = self.builder.newVariable(s.name) 29 v = self.builder.newTmp(s.name)
27 #self.builder.addIns(ir.Alloc(v)) 30 #self.builder.addIns(ir.Alloc(v))
28 self.varMap[s] = v 31 self.varMap[s] = v
29 elif type(s) is astnodes.Function: 32 elif type(s) is astnodes.Function:
30 # TODO: handle arguments 33 # TODO: handle arguments
31 f = self.funcMap[s] 34 f = self.funcMap[s]
54 if type(code) is astnodes.CompoundStatement: 57 if type(code) is astnodes.CompoundStatement:
55 for s in code.statements: 58 for s in code.statements:
56 self.genCode(s) 59 self.genCode(s)
57 elif type(code) is astnodes.Assignment: 60 elif type(code) is astnodes.Assignment:
58 re = self.genExprCode(code.rval) 61 re = self.genExprCode(code.rval)
59 # TODO: Handle pointers
60 loc = self.genExprCode(code.lval) 62 loc = self.genExprCode(code.lval)
61 # determine location of variable
62 self.builder.addIns(ir.Store(loc, re)) 63 self.builder.addIns(ir.Store(loc, re))
63 elif type(code) is astnodes.ExpressionStatement: 64 elif type(code) is astnodes.ExpressionStatement:
64 self.genExprCode(code.ex) 65 self.genExprCode(code.ex)
65 elif type(code) is astnodes.IfStatement: 66 elif type(code) is astnodes.IfStatement:
66 bbtrue = self.builder.newBB() 67 bbtrue = self.builder.newBB()
92 self.genCode(code.statement) 93 self.genCode(code.statement)
93 self.builder.addIns(ir.Branch(bbtest)) 94 self.builder.addIns(ir.Branch(bbtest))
94 self.builder.setBB(te) 95 self.builder.setBB(te)
95 else: 96 else:
96 print('Unknown stmt:', code) 97 print('Unknown stmt:', code)
98
97 def genCondCode(self, expr, bbtrue, bbfalse): 99 def genCondCode(self, expr, bbtrue, bbfalse):
98 # Implement sequential logical operators 100 # Implement sequential logical operators
99 assert expr.typ == boolType 101 assert expr.typ == boolType
100 if type(expr) is astnodes.Binop: 102 if type(expr) is astnodes.Binop:
101 if expr.op == 'or': 103 if expr.op == 'or':
120 self.builder.addIns(ir.Branch(bbtrue)) 122 self.builder.addIns(ir.Branch(bbtrue))
121 else: 123 else:
122 self.builder.addIns(ir.Branch(bbfalse)) 124 self.builder.addIns(ir.Branch(bbfalse))
123 else: 125 else:
124 print('Unknown cond', expr) 126 print('Unknown cond', expr)
127
128 def cast_to_rvalue(self, expr, loc):
129 """ Cast lvalue to rvalue if required """
130 if hasattr(expr, 'expect_rvalue'):
131 # Load value from memory location:
132 tmp = self.builder.newTmp()
133 i = ir.Load(loc, tmp)
134 self.builder.addIns(i)
135 return tmp
136 if expr.lvalue:
137 return loc
138
125 def genExprCode(self, expr): 139 def genExprCode(self, expr):
140 assert isinstance(expr, astnodes.Expression)
126 if type(expr) is astnodes.Binop: 141 if type(expr) is astnodes.Binop:
127 ra = self.genExprCode(expr.a) 142 ra = self.genExprCode(expr.a)
128 rb = self.genExprCode(expr.b) 143 rb = self.genExprCode(expr.b)
129 ops = ['+', '-', '*', '/', '|', '&'] 144 ops = ['+', '-', '*', '/', '|', '&']
130 if expr.op in ops: 145 if expr.op in ops:
131 tmpnames = {'+':'add', '-':'sub', '*': 'mul', '/':'div', '|':'or', '&':'and'}
132 tmp = self.builder.newTmp(tmpnames[expr.op]) 146 tmp = self.builder.newTmp(tmpnames[expr.op])
133 op = expr.op 147 op = expr.op
134 ins = ir.BinaryOperator(tmp, op, ra, rb) 148 ins = ir.BinaryOperator(tmp, op, ra, rb)
135 self.builder.addIns(ins) 149 self.builder.addIns(ins)
136 return tmp 150 return tmp
151 elif type(expr) is astnodes.Constant: 165 elif type(expr) is astnodes.Constant:
152 tmp = self.builder.newTmp() 166 tmp = self.builder.newTmp()
153 # TODO 167 # TODO
154 return tmp 168 return tmp
155 elif type(expr) is astnodes.VariableUse: 169 elif type(expr) is astnodes.VariableUse:
156 tmp = self.builder.newTmp()
157 loc = self.varMap[expr.target] 170 loc = self.varMap[expr.target]
158 i = ir.Load(loc, tmp) 171 return self.cast_to_rvalue(expr, loc)
159 self.builder.addIns(i)
160 return tmp
161 elif type(expr) is astnodes.Deref: 172 elif type(expr) is astnodes.Deref:
162 # dereference pointer type: 173 # dereference pointer type:
163 addr = self.genExprCode(expr.ptr) 174 addr = self.genExprCode(expr.ptr)
164 tmp = self.builder.newTmp('deref') 175 tmp = self.builder.newTmp('deref')
165 ins = ir.Load(addr, tmp) 176 ins = ir.Load(addr, tmp)
166 self.builder.addIns(ins) 177 self.builder.addIns(ins)
167 return tmp 178 return tmp
168 elif type(expr) is astnodes.FieldRef: 179 elif type(expr) is astnodes.FieldRef:
169 tmp = self.builder.newTmp('struct_mem' + expr.field) 180 b = self.genExprCode(expr.base)
170 #ins = ir.BinaryOperator( 181 offset = self.builder.newTmp('off_' + expr.field)
171 # TODO: add offset? 182 bt = resolveType(expr.base.typ)
172 return tmp 183 ofs = bt.fieldOffset(expr.field)
184 ins = ir.ImmLoad(offset, ofs)
185 self.builder.addIns(ins)
186 tmp2 = self.builder.newTmp('adr_' + expr.field)
187 ins = ir.BinaryOperator(tmp2, '+', b, offset)
188 self.builder.addIns(ins)
189 return self.cast_to_rvalue(expr, tmp2)
173 elif type(expr) is astnodes.Literal: 190 elif type(expr) is astnodes.Literal:
174 tmp = self.builder.newTmp() 191 tmp = self.builder.newTmp()
175 ins = ir.ImmLoad(tmp, expr.val) 192 ins = ir.ImmLoad(tmp, expr.val)
176 self.builder.addIns(ins) 193 self.builder.addIns(ins)
177 return tmp 194 return tmp
178 elif type(expr) is astnodes.TypeCast: 195 elif type(expr) is astnodes.TypeCast:
179 ar = self.genExprCode(expr.a) 196 ar = self.genExprCode(expr.a)
180 if isinstance(expr.to_type, astnodes.PointerType): 197 tt = resolveType(expr.to_type)
198 if isinstance(tt, astnodes.PointerType):
181 if expr.a.typ is intType: 199 if expr.a.typ is intType:
182 return ar 200 return ar
183 elif isinstance(expr.a.typ, astnodes.PointerType): 201 elif isinstance(expr.a.typ, astnodes.PointerType):
184 return ar 202 return ar
185 else: 203 else:
186 raise Exception() 204 raise Exception()
205 else:
206 raise Exception("not implemented")
187 elif type(expr) is astnodes.FunctionCall: 207 elif type(expr) is astnodes.FunctionCall:
188 tmp = self.builder.newTmp("res") 208 tmp = self.builder.newTmp("res")
189 args = [] 209 args = []
190 for arg in expr.args: 210 for arg in expr.args:
191 ar = self.genExprCode(arg) 211 ar = self.genExprCode(arg)