103
|
1 """
|
|
2 Generates ir code from ast tree.
|
|
3 """
|
|
4
|
|
5 from .nodes import *
|
|
6 from ...core.errors import Error
|
|
7 from ... import core
|
|
8 from .builtin import real, integer, boolean, char
|
|
9
|
|
10 class KsIrGenerator:
|
|
11 def __init__(self):
|
|
12 pass
|
|
13
|
|
14 # Code generation functions:
|
|
15 def genexprcode(self, node):
|
|
16 """
|
|
17 Generate code for expressions!
|
|
18 Recursively evaluates, and ensures a register contains the answer.
|
|
19 register is an integer register or a floating point reg
|
|
20 """
|
|
21 if isinstance(node, Binop):
|
|
22 """ Handle a binary operation (two arguments) of some kind """
|
|
23 self.genexprcode(node.a)
|
|
24 self.genexprcode(node.b)
|
|
25
|
|
26 if node.op == 'mod':
|
|
27 assert(node.typ.isType(integer))
|
|
28 elif node.op == 'div':
|
|
29 assert(node.typ.isType(integer))
|
|
30 elif node.op == '*':
|
|
31 if node.typ.isType(integer):
|
104
|
32 pass
|
103
|
33 elif node.op == '+':
|
|
34 if node.typ.isType(integer):
|
104
|
35 pass
|
103
|
36 elif node.op == '-':
|
|
37 if node.typ.isType(integer):
|
104
|
38 pass
|
103
|
39 else:
|
|
40 Error('Unknown Binop {0}'.format(node.op))
|
|
41
|
|
42 elif type(node) is Unop:
|
|
43 if node.op == 'INTTOREAL':
|
|
44 self.genexprcode(node.a)
|
|
45 code.append('Unop inttoreal TODO')
|
|
46 elif node.op == 'ABS':
|
|
47 if isType(node.typ, real):
|
|
48 Error('ABS error integer')
|
|
49 elif isType(node.typ, integer):
|
|
50 code = []
|
|
51 Error('ABS error integer')
|
|
52 else:
|
|
53 Error('ABS error')
|
|
54 else:
|
|
55 Error('Unknown Unop {0}'.format(node.op))
|
|
56
|
|
57 elif isinstance(node, Designator):
|
|
58 # dereference, array index. Make sure that the result comes into a register
|
|
59 if len(node.selectors) > 0:
|
|
60 self.gencode(node) # Load the pointer into some register
|
|
61
|
|
62 # Now we can access the object at location '[node.reg]':
|
|
63 if node.typ.isType(integer):
|
|
64 self.addCode( mov(node.reg, [node.reg, 0x0]) )
|
|
65 else:
|
|
66 Error('Only integer types implemented')
|
|
67 else:
|
|
68 # No selectors, load variable directly
|
|
69 if node.obj.typ.isType(integer):
|
|
70 if type(node.obj) is Constant:
|
|
71 self.genexprcode(node.obj)
|
|
72 node.reg = node.obj.reg
|
|
73 else:
|
104
|
74 pass
|
103
|
75 # Get a register to store the integer value
|
|
76 else:
|
|
77 Error('Cannot load variable type {0}'.format(node.typ))
|
|
78
|
|
79 elif isinstance(node, Relop):
|
|
80 # Create a boolean from operands
|
|
81 # TODO create an alternative for expressions used as conditions.
|
|
82 self.genexprcode(node.a)
|
|
83 self.genexprcode(node.b)
|
|
84
|
|
85 if node.a.typ.isType(integer):
|
|
86 self.freereg(node.b)
|
|
87 else:
|
|
88 Error('Relop not implemented for {0}'.format(node.a.typ))
|
|
89
|
|
90 elif type(node) is Constant:
|
104
|
91 print('TODO: constant')
|
103
|
92
|
|
93 elif type(node) is ProcedureCall:
|
104
|
94 Error('TODO: proc call')
|
103
|
95 else:
|
|
96 Error('Cannot generate expression code for: {0}'.format(node))
|
|
97
|
|
98 def gencode(self, node):
|
|
99 """ Code generation function for AST nodes """
|
|
100 if isinstance(node, Module):
|
|
101 # TODO: recurse!
|
104
|
102
|
|
103 self.mod = core.Module()
|
|
104 # Create a function called init for this module:
|
|
105 ftype = core.FunctionType(self.context.VoidType, [])
|
|
106 func = core.Function(ftype, "init", self.mod)
|
|
107 bb = self.gencode(node.initcode)
|
|
108 self.mod.dump()
|
|
109 return self.mod
|
103
|
110
|
|
111 elif type(node) is Procedure:
|
|
112 # calculate offsets for local variables and parameters
|
|
113 # Variable location relative to 'rbp' register
|
|
114 variables = node.symtable.getAllLocal(Variable)
|
|
115
|
|
116 elif isinstance(node, StatementSequence):
|
|
117 for s in node.statements:
|
|
118 self.gencode(s)
|
|
119
|
|
120 elif type(node) is ProcedureCall:
|
|
121 # Prepare parameters on the stack:
|
|
122 assert(len(node.args) == len(node.proc.typ.parameters))
|
|
123 for arg, param in zip(node.args, node.proc.typ.parameters):
|
|
124
|
|
125 if param.kind == 'value':
|
|
126 self.genexprcode(arg)
|
|
127 self.addCode( push(arg.reg) )
|
|
128 self.freereg( arg )
|
|
129 stacksize += 8
|
|
130 else:
|
|
131 Error('Parameter kind other than value')
|
|
132
|
|
133 elif type(node) is Assignment:
|
|
134 if node.lval.typ.isType(integer):
|
|
135 # TODO if node.rval is Constant of some datatype, move it to mem directly
|
|
136 self.genexprcode(node.rval) # Calculate the value that has to be stored.
|
104
|
137 print("TODO")
|
103
|
138 else:
|
|
139 Error('Assignments of other types not implemented')
|
|
140 # TODO if left and right are designators, do some sort of memcpy.
|
|
141
|
|
142 elif type(node) is IfStatement:
|
|
143 self.genexprcode(node.condition)
|
104
|
144 print("TODO IF")
|
103
|
145 if node.falsestatement:
|
|
146 # If with else clause
|
104
|
147 pass
|
103
|
148 else:
|
|
149 # If without else clause
|
104
|
150 pass
|
103
|
151
|
|
152 elif isinstance(node, WhileStatement):
|
|
153 self.genexprcode(node.condition)
|
|
154 self.gencode(node.dostatements)
|
|
155 elif type(node) is ForStatement:
|
|
156 # Initial load of iterator variable:
|
|
157 self.genexprcode(node.begin)
|
|
158 self.genexprcode(node.end)
|
|
159 self.gencode(node.statements)
|
|
160 Error('No implementation of FOR statement')
|
|
161
|
|
162 elif type(node) is AsmCode:
|
|
163 def processOperand(op):
|
|
164 if type(op) is list:
|
|
165 if type(op[0]) is Variable:
|
|
166 var = op[0]
|
|
167 if var.isLocal:
|
|
168 return ['rbp', var.offset]
|
|
169 else:
|
|
170 Error('Can only use local variables in inline assembler')
|
|
171 return op
|
|
172 for asmline in node.asmcode:
|
|
173 opcode, operands = asmline
|
|
174 operands = [processOperand(opx) for opx in operands]
|
|
175 print('assembling', opcode, *operands)
|
|
176 func,nargs = opcodes[opcode]
|
|
177 code = func(*operands)
|
|
178 self.addCode(code)
|
|
179
|
|
180 elif isinstance(node, EmptyStatement):
|
|
181 pass
|
|
182
|
|
183 elif type(node) is StringConstant:
|
|
184 self.strings.append(node)
|
|
185 self.data.append(node.value) # Add string to the data section
|
|
186
|
|
187 elif type(node) is Designator:
|
|
188 if len(node.selectors) > 0:
|
|
189 self.getreg(node)
|
|
190 # Load starting address
|
|
191 if node.obj.isLocal:
|
|
192 self.addCode( leareg64(node.reg, ['rbp', node.obj.offset]) )
|
|
193 else:
|
|
194 # Global variables need to be relocated...
|
|
195 self.addCode(leareg64(node.reg, ['RIP', 0]))
|
|
196 self.fixCode(self.rip - 4, imm32(node.obj.offset - self.rip))
|
|
197 # Loop over all designators..
|
|
198 for selector in node.selectors:
|
|
199 if type(selector) is Index:
|
|
200 # Deref an array index
|
|
201 self.genexprcode(selector.index)
|
|
202 self.freereg(selector)
|
|
203 elif type(selector) is Field:
|
|
204 print('Field')
|
|
205 Error('Field not implemented')
|
|
206 else:
|
|
207 Error('Unknown selector')
|
|
208 else:
|
|
209 Error('Can only gencode for designator with selectors')
|
|
210 else:
|
|
211 print('not generating code for {0}'.format(node))
|
|
212
|
104
|
213 def generateIr(self, context, ast):
|
103
|
214 """ ir generation front end """
|
104
|
215 # Create a new context for this code.
|
|
216 self.context = context
|
103
|
217 return self.gencode(ast)
|
|
218
|