Mercurial > lcfOS
annotate python/c3/codegenerator.py @ 220:3f6c30a5d234
Major change in expression parsing to enable pointers and structs
author | Windel Bouwman |
---|---|
date | Sat, 06 Jul 2013 21:32:20 +0200 |
parents | 8b2e5f3cd579 |
children | 848c4b15fd0b |
rev | line source |
---|---|
155 | 1 import ir |
2 from . import astnodes | |
171 | 3 from .scope import boolType |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
217
diff
changeset
|
4 from ppci import CompilerError |
171 | 5 |
170 | 6 class CodeGenerator: |
217 | 7 """ Generates intermediate code from a package """ |
8 def gencode(self, pkg): | |
9 assert type(pkg) is astnodes.Package | |
10 self.varMap = {} # Maps variables to storage locations. | |
11 self.funcMap = {} | |
12 self.builder = ir.Builder() | |
13 m = ir.Module(pkg.name) | |
14 self.builder.setModule(m) | |
15 self.genModule(pkg) | |
16 return m | |
170 | 17 |
217 | 18 # inner helpers: |
19 def genModule(self, pkg): | |
175 | 20 # Take care of forward declarations: |
217 | 21 for s in pkg.innerScope.Functions: |
204 | 22 f = self.builder.newFunction(s.name) |
175 | 23 self.funcMap[s] = f |
217 | 24 for s in pkg.innerScope: |
170 | 25 if type(s) is astnodes.Variable: |
205 | 26 v = self.builder.newVariable(s.name) |
186 | 27 #self.builder.addIns(ir.Alloc(v)) |
28 self.varMap[s] = v | |
170 | 29 elif type(s) is astnodes.Function: |
30 # TODO: handle arguments | |
175 | 31 f = self.funcMap[s] |
204 | 32 self.builder.setFunction(f) |
171 | 33 bb = self.builder.newBB() |
172 | 34 f.entry = bb |
171 | 35 self.builder.setBB(bb) |
174 | 36 # generate room for locals: |
37 | |
217 | 38 for sym in s.innerScope: |
175 | 39 #print(sym, sym.isParameter) |
40 # TODO: handle parameters different | |
174 | 41 v = self.builder.newTmp(sym.name) |
42 self.builder.addIns(ir.Alloc(v)) | |
43 self.varMap[sym] = v | |
44 | |
170 | 45 self.genCode(s.body) |
172 | 46 # TODO handle return? |
171 | 47 self.builder.addIns(ir.Return()) |
204 | 48 self.builder.setFunction(None) |
170 | 49 else: |
50 print(s) | |
158 | 51 |
217 | 52 def genCode(self, code): |
170 | 53 if type(code) is astnodes.CompoundStatement: |
54 for s in code.statements: | |
55 self.genCode(s) | |
56 elif type(code) is astnodes.Assignment: | |
57 re = self.genExprCode(code.rval) | |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
217
diff
changeset
|
58 # TODO: Handle pointers |
174 | 59 loc = self.varMap[code.lval.target] |
60 self.builder.addIns(ir.Store(loc, re)) | |
170 | 61 elif type(code) is astnodes.IfStatement: |
171 | 62 bbtrue = self.builder.newBB() |
63 bbfalse = self.builder.newBB() | |
64 te = self.builder.newBB() | |
65 self.genCondCode(code.condition, bbtrue, bbfalse) | |
66 self.builder.setBB(bbtrue) | |
170 | 67 self.genCode(code.truestatement) |
171 | 68 self.builder.addIns(ir.Branch(te)) |
69 self.builder.setBB(bbfalse) | |
170 | 70 self.genCode(code.falsestatement) |
171 | 71 self.builder.addIns(ir.Branch(te)) |
72 self.builder.setBB(te) | |
170 | 73 elif type(code) is astnodes.FunctionCall: |
176 | 74 print('TODO') |
170 | 75 pass |
76 elif type(code) is astnodes.EmptyStatement: | |
77 pass | |
78 elif type(code) is astnodes.ReturnStatement: | |
174 | 79 if code.expr: |
80 re = self.genExprCode(code.expr) | |
81 self.builder.addIns(ir.Return(re)) | |
82 else: | |
83 self.builder.addIns(ir.Return()) | |
176 | 84 elif type(code) is astnodes.WhileStatement: |
85 bbdo = self.builder.newBB() | |
86 bbtest = self.builder.newBB() | |
87 te = self.builder.newBB() | |
88 self.builder.addIns(ir.Branch(bbtest)) | |
89 self.builder.setBB(bbtest) | |
90 self.genCondCode(code.condition, bbdo, te) | |
91 self.builder.setBB(bbdo) | |
217 | 92 self.genCode(code.statement) |
176 | 93 self.builder.addIns(ir.Branch(bbtest)) |
94 self.builder.setBB(te) | |
170 | 95 else: |
96 print('Unknown stmt:', code) | |
217 | 97 def genCondCode(self, expr, bbtrue, bbfalse): |
171 | 98 # Implement sequential logical operators |
99 assert expr.typ == boolType | |
100 if type(expr) is astnodes.Binop: | |
101 if expr.op == 'or': | |
102 l2 = self.builder.newBB() | |
103 self.genCondCode(expr.a, bbtrue, l2) | |
104 self.builder.setBB(l2) | |
105 self.genCondCode(expr.b, bbtrue, bbfalse) | |
106 elif expr.op == 'and': | |
107 l2 = self.builder.newBB() | |
108 self.genCondCode(expr.a, l2, bbfalse) | |
109 self.builder.setBB(l2) | |
110 self.genCondCode(expr.b, bbtrue, bbfalse) | |
111 elif expr.op in ['==', '>', '<']: | |
112 ta = self.genExprCode(expr.a) | |
113 tb = self.genExprCode(expr.b) | |
114 i = ir.ConditionalBranch(ta, expr.op, tb, bbtrue, bbfalse) | |
115 self.builder.addIns(i) | |
116 else: | |
174 | 117 raise NotImlementedError('Unknown condition {0}'.format(expr)) |
171 | 118 elif type(expr) is astnodes.Literal: |
119 if expr.val: | |
205 | 120 self.builder.addIns(ir.Branch(bbtrue)) |
171 | 121 else: |
205 | 122 self.builder.addIns(ir.Branch(bbfalse)) |
171 | 123 else: |
124 print('Unknown cond', expr) | |
217 | 125 def genExprCode(self, expr): |
170 | 126 if type(expr) is astnodes.Binop: |
127 ra = self.genExprCode(expr.a) | |
128 rb = self.genExprCode(expr.b) | |
177 | 129 ops = ['+', '-', '*', '/'] |
170 | 130 if expr.op in ops: |
177 | 131 tmpnames = {'+':'addtmp', '-':'subtmp', '*': 'multmp', '/':'divtmp'} |
132 tmp = self.builder.newTmp(tmpnames[expr.op]) | |
170 | 133 op = expr.op |
134 ins = ir.BinaryOperator(tmp, op, ra, rb) | |
171 | 135 self.builder.addIns(ins) |
170 | 136 return tmp |
137 else: | |
171 | 138 print('Unknown {0}'.format(expr)) |
177 | 139 tmp = self.builder.newTmp() |
171 | 140 # TODO |
141 return tmp | |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
217
diff
changeset
|
142 elif type(expr) is astnodes.Unop: |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
217
diff
changeset
|
143 if expr.op == '&': |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
217
diff
changeset
|
144 # Address of operator |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
217
diff
changeset
|
145 ra = self.genExprCode(expr.a) |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
217
diff
changeset
|
146 tmp = self.builder.newTmp('addr') |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
217
diff
changeset
|
147 return tmp |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
217
diff
changeset
|
148 #self.builder.addIns(ins) |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
217
diff
changeset
|
149 else: |
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
217
diff
changeset
|
150 print('Unknown {0}'.format(expr)) |
170 | 151 elif type(expr) is astnodes.Constant: |
171 | 152 tmp = self.builder.newTmp() |
153 # TODO | |
154 return tmp | |
170 | 155 elif type(expr) is astnodes.VariableUse: |
171 | 156 tmp = self.builder.newTmp() |
174 | 157 loc = self.varMap[expr.target] |
158 i = ir.Load(loc, tmp) | |
171 | 159 self.builder.addIns(i) |
160 return tmp | |
170 | 161 elif type(expr) is astnodes.Literal: |
171 | 162 tmp = self.builder.newTmp() |
163 ins = ir.ImmLoad(tmp, expr.val) | |
164 self.builder.addIns(ins) | |
158 | 165 return tmp |
175 | 166 elif type(expr) is astnodes.FunctionCall: |
167 tmp = self.builder.newTmp("res") | |
168 args = [] | |
169 for arg in expr.args: | |
170 ar = self.genExprCode(arg) | |
171 args.append(ar) | |
172 fn = self.funcMap[expr.proc] | |
173 ins = ir.Call(fn, args, tmp) | |
174 self.builder.addIns(ins) | |
175 return tmp | |
157 | 176 else: |
220
3f6c30a5d234
Major change in expression parsing to enable pointers and structs
Windel Bouwman
parents:
217
diff
changeset
|
177 raise CompilerError('Unknown expr {}'.format(expr)) |
157 | 178 |