Mercurial > lcfOS
comparison python/c3/codegenerator.py @ 171:3eb9b9e2958d
Improved IR code
author | Windel Bouwman |
---|---|
date | Wed, 03 Apr 2013 22:20:20 +0200 |
parents | 4348da5ca307 |
children | 5a7d37d615ee |
comparison
equal
deleted
inserted
replaced
170:4348da5ca307 | 171:3eb9b9e2958d |
---|---|
1 import ir | 1 import ir |
2 from . import astnodes | 2 from . import astnodes |
3 | 3 from .scope import boolType |
4 def NumGen(): | 4 |
5 a = 0 | |
6 while True: | |
7 yield a | |
8 a = a + 1 | |
9 | |
10 class NameGenerator: | |
11 def __init__(self, prefix): | |
12 self.prefix = prefix | |
13 self.nums = NumGen() | |
14 def gen(self): | |
15 return '{0}{1}'.format(self.prefix, self.nums.__next__()) | |
16 | |
17 class CodeGenerator: | 5 class CodeGenerator: |
18 """ Generates intermediate code from a package """ | 6 """ Generates intermediate code from a package """ |
19 def gencode(self, pkg): | 7 def gencode(self, pkg): |
20 assert type(pkg) is astnodes.Package | 8 assert type(pkg) is astnodes.Package |
21 self.m = ir.Module(pkg.name) | 9 self.builder = ir.Builder() |
22 self.newTmp = NameGenerator('t').gen | 10 m = ir.Module(pkg.name) |
23 self.newLab = NameGenerator('lab').gen | 11 self.builder.setModule(m) |
24 self.genModule(pkg) | 12 self.genModule(pkg) |
25 return self.m | 13 return m |
26 | 14 |
27 # Helpers: | |
28 def addIns(self, i): | |
29 self.m.Instructions.append(i) | |
30 # inner helpers: | 15 # inner helpers: |
31 def genModule(self, pkg): | 16 def genModule(self, pkg): |
32 for s in pkg.scope: | 17 for s in pkg.scope: |
33 if type(s) is astnodes.Variable: | 18 if type(s) is astnodes.Variable: |
34 # TODO | 19 # TODO |
35 pass | 20 pass |
36 elif type(s) is astnodes.Function: | 21 elif type(s) is astnodes.Function: |
37 # TODO: handle arguments | 22 # TODO: handle arguments |
38 # TODO handle return? | 23 # TODO handle return? |
39 self.addIns(ir.LabelInstruction(s.name)) | 24 bb = self.builder.newBB() |
25 self.builder.setBB(bb) | |
40 self.genCode(s.body) | 26 self.genCode(s.body) |
41 self.addIns(ir.RetInstruction()) | 27 self.builder.addIns(ir.Return()) |
42 else: | 28 else: |
43 print(s) | 29 print(s) |
44 | 30 |
45 def genCode(self, code): | 31 def genCode(self, code): |
46 if type(code) is astnodes.CompoundStatement: | 32 if type(code) is astnodes.CompoundStatement: |
47 for s in code.statements: | 33 for s in code.statements: |
48 self.genCode(s) | 34 self.genCode(s) |
49 elif type(code) is astnodes.Assignment: | 35 elif type(code) is astnodes.Assignment: |
50 re = self.genExprCode(code.rval) | 36 re = self.genExprCode(code.rval) |
51 self.addIns(ir.StoreInstruction(code.lval, re)) | 37 self.builder.addIns(ir.Store(code.lval, re)) |
52 elif type(code) is astnodes.IfStatement: | 38 elif type(code) is astnodes.IfStatement: |
53 cr = self.genExprCode(code.condition) | 39 bbtrue = self.builder.newBB() |
54 t1, t2, te = self.newLab(), self.newLab(), self.newLab() | 40 bbfalse = self.builder.newBB() |
55 self.addIns(ir.IfInstruction(cr, t1, t2)) | 41 te = self.builder.newBB() |
56 self.addIns(ir.LabelInstruction(t1)) | 42 self.genCondCode(code.condition, bbtrue, bbfalse) |
43 self.builder.setBB(bbtrue) | |
57 self.genCode(code.truestatement) | 44 self.genCode(code.truestatement) |
58 self.addIns(ir.BranchInstruction(te)) | 45 self.builder.addIns(ir.Branch(te)) |
59 self.addIns(ir.LabelInstruction(t2)) | 46 self.builder.setBB(bbfalse) |
60 self.genCode(code.falsestatement) | 47 self.genCode(code.falsestatement) |
61 self.addIns(ir.LabelInstruction(te)) | 48 self.builder.addIns(ir.Branch(te)) |
49 self.builder.setBB(te) | |
62 elif type(code) is astnodes.FunctionCall: | 50 elif type(code) is astnodes.FunctionCall: |
63 pass | 51 pass |
64 elif type(code) is astnodes.EmptyStatement: | 52 elif type(code) is astnodes.EmptyStatement: |
65 pass | 53 pass |
66 elif type(code) is astnodes.ReturnStatement: | 54 elif type(code) is astnodes.ReturnStatement: |
67 pass | 55 pass |
68 else: | 56 else: |
69 print('Unknown stmt:', code) | 57 print('Unknown stmt:', code) |
70 | 58 def genCondCode(self, expr, bbtrue, bbfalse): |
59 # Implement sequential logical operators | |
60 assert expr.typ == boolType | |
61 if type(expr) is astnodes.Binop: | |
62 if expr.op == 'or': | |
63 l2 = self.builder.newBB() | |
64 self.genCondCode(expr.a, bbtrue, l2) | |
65 self.builder.setBB(l2) | |
66 self.genCondCode(expr.b, bbtrue, bbfalse) | |
67 elif expr.op == 'and': | |
68 l2 = self.builder.newBB() | |
69 self.genCondCode(expr.a, l2, bbfalse) | |
70 self.builder.setBB(l2) | |
71 self.genCondCode(expr.b, bbtrue, bbfalse) | |
72 elif expr.op in ['==', '>', '<']: | |
73 ta = self.genExprCode(expr.a) | |
74 tb = self.genExprCode(expr.b) | |
75 i = ir.ConditionalBranch(ta, expr.op, tb, bbtrue, bbfalse) | |
76 self.builder.addIns(i) | |
77 else: | |
78 raise NotImlementedError() | |
79 print('Unknown cond', expr) | |
80 elif type(expr) is astnodes.Literal: | |
81 if expr.val: | |
82 self.builder.addIns(ir.BranchInstruction(bbtrue)) | |
83 else: | |
84 self.builder.addIns(ir.BranchInstruction(bbfalse)) | |
85 else: | |
86 print('Unknown cond', expr) | |
71 def genExprCode(self, expr): | 87 def genExprCode(self, expr): |
72 if type(expr) is astnodes.Binop: | 88 if type(expr) is astnodes.Binop: |
73 ra = self.genExprCode(expr.a) | 89 ra = self.genExprCode(expr.a) |
74 rb = self.genExprCode(expr.b) | 90 rb = self.genExprCode(expr.b) |
91 tmp = self.builder.newTmp() | |
75 ops = ['+', '-', '*', '/', 'and', 'or'] | 92 ops = ['+', '-', '*', '/', 'and', 'or'] |
76 if expr.op in ops: | 93 if expr.op in ops: |
77 op = expr.op | 94 op = expr.op |
78 tmp = self.newTmp() | |
79 ins = ir.BinaryOperator(tmp, op, ra, rb) | 95 ins = ir.BinaryOperator(tmp, op, ra, rb) |
80 self.addIns(ins) | 96 self.builder.addIns(ins) |
81 return tmp | 97 return tmp |
82 else: | 98 else: |
83 print('Unknown binop {0}'.format(expr)) | 99 print('Unknown {0}'.format(expr)) |
100 # TODO | |
101 return tmp | |
84 elif type(expr) is astnodes.Constant: | 102 elif type(expr) is astnodes.Constant: |
85 tmp = unique() | 103 tmp = self.builder.newTmp() |
104 # TODO | |
105 return tmp | |
86 elif type(expr) is astnodes.VariableUse: | 106 elif type(expr) is astnodes.VariableUse: |
87 tmp = self.newTmp() | 107 tmp = self.builder.newTmp() |
108 i = ir.Load(expr, tmp) | |
109 self.builder.addIns(i) | |
110 return tmp | |
88 elif type(expr) is astnodes.Literal: | 111 elif type(expr) is astnodes.Literal: |
89 tmp = self.newTmp() | 112 tmp = self.builder.newTmp() |
90 ins = ir.MoveInstruction(tmp, expr.val) | 113 ins = ir.ImmLoad(tmp, expr.val) |
91 self.addIns(ins) | 114 self.builder.addIns(ins) |
92 return tmp | 115 return tmp |
93 else: | 116 else: |
94 print('Unknown expr:', code) | 117 print('Unknown expr:', code) |
95 | 118 |