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