Mercurial > lcfOS
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) |