Mercurial > lcfOS
comparison python/ppci/frontends/ks/irgenerator.py @ 104:ed230e947dc6
Added hexviewer
author | windel |
---|---|
date | Sun, 30 Dec 2012 22:31:55 +0100 |
parents | 28a35161ef23 |
children | f2d980eef509 |
comparison
equal
deleted
inserted
replaced
103:28a35161ef23 | 104:ed230e947dc6 |
---|---|
4 | 4 |
5 from .nodes import * | 5 from .nodes import * |
6 from ...core.errors import Error | 6 from ...core.errors import Error |
7 from ... import core | 7 from ... import core |
8 from .builtin import real, integer, boolean, char | 8 from .builtin import real, integer, boolean, char |
9 #from .assembler import * | |
10 | 9 |
11 class KsIrGenerator: | 10 class KsIrGenerator: |
12 def __init__(self): | 11 def __init__(self): |
13 pass | 12 pass |
14 | 13 |
24 self.genexprcode(node.a) | 23 self.genexprcode(node.a) |
25 self.genexprcode(node.b) | 24 self.genexprcode(node.b) |
26 | 25 |
27 if node.op == 'mod': | 26 if node.op == 'mod': |
28 assert(node.typ.isType(integer)) | 27 assert(node.typ.isType(integer)) |
29 self.addCode(mov('rax', node.a.reg)) | |
30 elif node.op == 'div': | 28 elif node.op == 'div': |
31 assert(node.typ.isType(integer)) | 29 assert(node.typ.isType(integer)) |
32 self.addCode(mov('rax', node.a.reg)) | |
33 elif node.op == '*': | 30 elif node.op == '*': |
34 if node.typ.isType(integer): | 31 if node.typ.isType(integer): |
35 self.addCode(imulreg64(node.a.reg, node.b.reg)) | 32 pass |
36 elif node.op == '+': | 33 elif node.op == '+': |
37 if node.typ.isType(integer): | 34 if node.typ.isType(integer): |
38 self.addCode(addreg64(node.a.reg, node.b.reg)) | 35 pass |
39 elif node.op == '-': | 36 elif node.op == '-': |
40 if node.typ.isType(integer): | 37 if node.typ.isType(integer): |
41 self.addCode(subreg64(node.a.reg, node.b.reg)) | 38 pass |
42 else: | 39 else: |
43 Error('Unknown Binop {0}'.format(node.op)) | 40 Error('Unknown Binop {0}'.format(node.op)) |
44 | 41 |
45 elif type(node) is Unop: | 42 elif type(node) is Unop: |
46 if node.op == 'INTTOREAL': | 43 if node.op == 'INTTOREAL': |
76 if node.obj.typ.isType(integer): | 73 if node.obj.typ.isType(integer): |
77 if type(node.obj) is Constant: | 74 if type(node.obj) is Constant: |
78 self.genexprcode(node.obj) | 75 self.genexprcode(node.obj) |
79 node.reg = node.obj.reg | 76 node.reg = node.obj.reg |
80 else: | 77 else: |
81 self.getreg(node) | 78 pass |
82 # Get a register to store the integer value | 79 # Get a register to store the integer value |
83 if node.obj.isLocal: | |
84 # relative to rbp: | |
85 self.addCode( mov(node.reg, ['rbp', node.obj.offset]) ) | |
86 else: | |
87 self.addCode(mov(node.reg, ['RIP', 0x0])) | |
88 self.fixCode(self.rip-4, imm32(node.obj.offset - self.rip)) | |
89 else: | 80 else: |
90 Error('Cannot load variable type {0}'.format(node.typ)) | 81 Error('Cannot load variable type {0}'.format(node.typ)) |
91 | 82 |
92 elif isinstance(node, Relop): | 83 elif isinstance(node, Relop): |
93 # Create a boolean from operands | 84 # Create a boolean from operands |
99 self.freereg(node.b) | 90 self.freereg(node.b) |
100 else: | 91 else: |
101 Error('Relop not implemented for {0}'.format(node.a.typ)) | 92 Error('Relop not implemented for {0}'.format(node.a.typ)) |
102 | 93 |
103 elif type(node) is Constant: | 94 elif type(node) is Constant: |
104 if node.typ.isType(integer): | 95 print('TODO: constant') |
105 self.getreg(node) | |
106 | 96 |
107 elif type(node) is ProcedureCall: | 97 elif type(node) is ProcedureCall: |
108 if type(node.proc.obj) is BuiltinProcedure: | 98 Error('TODO: proc call') |
109 # Handle builtin procedures different, these not always call | |
110 # a function, but generate code. | |
111 bi = node.proc.obj | |
112 if bi.name == 'chr': | |
113 arg = node.args[0] | |
114 self.genexprcode(arg) | |
115 # Store character in full width register: | |
116 # TODO: store in char only register | |
117 node.reg = arg.reg | |
118 else: | |
119 Error('Unknown builtin function {0}'.format(bi.name)) | |
120 else: | |
121 # Use generic procedure call first | |
122 self.gencode(node) | |
123 # Retrieve result: | |
124 if node.typ.isType(integer): | |
125 # Store result! | |
126 self.getreg(node) | |
127 self.addCode( mov(node.reg, 'rax') ) | |
128 else: | |
129 Error('Return type not supported {0}'.format(node.typ)) | |
130 else: | 99 else: |
131 Error('Cannot generate expression code for: {0}'.format(node)) | 100 Error('Cannot generate expression code for: {0}'.format(node)) |
132 | 101 |
133 def gencode(self, node): | 102 def gencode(self, node): |
134 """ Code generation function for AST nodes """ | 103 """ Code generation function for AST nodes """ |
135 if isinstance(node, Module): | 104 if isinstance(node, Module): |
136 # TODO: recurse! | 105 # TODO: recurse! |
137 return core.Module() | 106 |
107 self.mod = core.Module() | |
108 # Create a function called init for this module: | |
109 ftype = core.FunctionType(self.context.VoidType, []) | |
110 func = core.Function(ftype, "init", self.mod) | |
111 bb = self.gencode(node.initcode) | |
112 self.mod.dump() | |
113 return self.mod | |
138 | 114 |
139 elif type(node) is Procedure: | 115 elif type(node) is Procedure: |
140 # calculate offsets for local variables and parameters | 116 # calculate offsets for local variables and parameters |
141 # Variable location relative to 'rbp' register | 117 # Variable location relative to 'rbp' register |
142 variables = node.symtable.getAllLocal(Variable) | 118 variables = node.symtable.getAllLocal(Variable) |
143 offset = 0 | |
144 paramoffset = 16 | |
145 for var in variables: | |
146 var.isLocal = True | |
147 if not var.isParameter: | |
148 offset += var.typ.size | |
149 # Offset is negative of rbp in stack frame | |
150 var.offset = -offset | |
151 node.framesize = offset | |
152 # Calculate offsets of parameters relative to rbp register | |
153 for par in reversed(node.typ.parameters): | |
154 pvar = node.symtable.getLocal(Variable, par.name) | |
155 pvar.offset = paramoffset | |
156 paramoffset += pvar.typ.size | |
157 | |
158 # code generation | |
159 node.entrypoint = self.rip | |
160 self.addCode(push('rbp')) | |
161 self.addCode(mov('rbp', 'rsp')) # Setup the base pointer | |
162 self.addCode(subreg64('rsp', node.framesize)) # reserve space for locals | |
163 self.gencode(node.block) | |
164 if node.retexpr: | |
165 if node.retexpr.typ.isType(integer): | |
166 self.genexprcode(node.retexpr) | |
167 self.addCode( mov('rax', node.retexpr.reg) ) | |
168 self.freereg(node.retexpr) | |
169 else: | |
170 Error('Cannot return this kind yet {0}'.format(node.retexpr.typ)) | |
171 self.addCode( addreg64('rsp', node.framesize) ) | |
172 self.addCode( pop('rbp') ) | |
173 self.addCode( ret() ) | |
174 assert(len(self.usedregs) == 0) | |
175 | 119 |
176 elif isinstance(node, StatementSequence): | 120 elif isinstance(node, StatementSequence): |
177 for s in node.statements: | 121 for s in node.statements: |
178 self.gencode(s) | 122 self.gencode(s) |
179 | 123 |
180 elif type(node) is ProcedureCall: | 124 elif type(node) is ProcedureCall: |
181 # Prepare parameters on the stack: | 125 # Prepare parameters on the stack: |
182 stacksize = 0 | |
183 assert(len(node.args) == len(node.proc.typ.parameters)) | 126 assert(len(node.args) == len(node.proc.typ.parameters)) |
184 for arg, param in zip(node.args, node.proc.typ.parameters): | 127 for arg, param in zip(node.args, node.proc.typ.parameters): |
185 | 128 |
186 if param.kind == 'value': | 129 if param.kind == 'value': |
187 self.genexprcode(arg) | 130 self.genexprcode(arg) |
189 self.freereg( arg ) | 132 self.freereg( arg ) |
190 stacksize += 8 | 133 stacksize += 8 |
191 else: | 134 else: |
192 Error('Parameter kind other than value') | 135 Error('Parameter kind other than value') |
193 | 136 |
194 # Calculate address using designator | |
195 if type(node.proc.obj) is Procedure: | |
196 self.addCode( call(0x0) ) | |
197 self.fixCode( self.rip - 4, imm32(node.proc.obj.entrypoint - self.rip)) | |
198 elif type(node.proc.obj) is ImportedSymbol: | |
199 # Load the entry point of the import table | |
200 self.getreg(node.proc.obj) | |
201 # Load the address of the procedure: | |
202 self.addCode( mov(node.proc.obj.reg, ['RIP', 0x0]) ) | |
203 self.fixCode( self.rip - 4, imm32(node.proc.obj.offset - self.rip) ) | |
204 # Call to the address in register: | |
205 self.addCode( call(node.proc.obj.reg) ) | |
206 # Free register that holds the address of the object | |
207 self.freereg( node.proc.obj ) | |
208 elif type(node.proc.obj) is BuiltinProcedure: | |
209 if node.proc.obj.name == 'chr': | |
210 print('int to char') | |
211 else: | |
212 Error('Unknown builtin function {0}'.format(node.proc.obj.name)) | |
213 else: | |
214 Error('Cannot call designator of type {0}'.format(node.proc.obj)) | |
215 | |
216 # Restore stack (pop all arguments of): | |
217 self.addCode(addreg64('rsp', stacksize)) | |
218 | |
219 elif type(node) is Assignment: | 137 elif type(node) is Assignment: |
220 if node.lval.typ.isType(integer): | 138 if node.lval.typ.isType(integer): |
221 # TODO if node.rval is Constant of some datatype, move it to mem directly | 139 # TODO if node.rval is Constant of some datatype, move it to mem directly |
222 self.genexprcode(node.rval) # Calculate the value that has to be stored. | 140 self.genexprcode(node.rval) # Calculate the value that has to be stored. |
223 self.storeRegInDesignator(node.rval.reg, node.lval) | 141 print("TODO") |
224 self.freereg(node.rval) | |
225 else: | 142 else: |
226 Error('Assignments of other types not implemented') | 143 Error('Assignments of other types not implemented') |
227 # TODO if left and right are designators, do some sort of memcpy. | 144 # TODO if left and right are designators, do some sort of memcpy. |
228 | 145 |
229 elif type(node) is IfStatement: | 146 elif type(node) is IfStatement: |
230 self.genexprcode(node.condition) | 147 self.genexprcode(node.condition) |
231 self.addCode( cmpreg64(node.condition.reg, 1) ) | 148 print("TODO IF") |
232 self.freereg(node.condition) | |
233 if node.falsestatement: | 149 if node.falsestatement: |
234 # If with else clause | 150 # If with else clause |
235 self.addCode( nearjump(0x0, condition='NE') ) # if Not Equal jump to false | 151 pass |
236 rip1 = self.rip | |
237 fixloc1 = self.rip - 4 | |
238 self.gencode(node.truestatement) | |
239 self.addCode( nearjump( 0x0 ) ) # jump over false code | |
240 fixloc2 = self.rip - 4 | |
241 self.fixCode(fixloc1, imm32(self.rip - rip1)) | |
242 rip2 = self.rip | |
243 self.gencode(node.falsestatement) | |
244 self.fixCode(fixloc2, imm32(self.rip - rip2)) | |
245 else: | 152 else: |
246 # If without else clause | 153 # If without else clause |
247 self.addCode( nearjump(0x0, condition='NE') ) # if Not Equal jump to false | 154 pass |
248 rip1 = self.rip | |
249 fixloc1 = self.rip - 4 | |
250 self.gencode(node.truestatement) | |
251 self.fixCode(fixloc1, imm32(self.rip - rip1)) # Fixup near jump over true code. | |
252 | 155 |
253 elif isinstance(node, WhileStatement): | 156 elif isinstance(node, WhileStatement): |
254 rip1 = self.rip # Store the start of the while loop | |
255 self.genexprcode(node.condition) | 157 self.genexprcode(node.condition) |
256 self.addCode( cmpreg64(node.condition.reg, 1) ) # Test condition for true-ness | |
257 self.freereg(node.condition) | |
258 self.addCode( nearjump(0x0, condition='NE') ) # If Not Equal jump over while code AND jump back (fix later) | |
259 fixloc1 = self.rip - 4 | |
260 rip2 = self.rip | |
261 self.gencode(node.dostatements) | 158 self.gencode(node.dostatements) |
262 self.addCode( nearjump(0x0) ) # JMP to condition, fix exact jump position below | |
263 fixloc2 = self.rip - 4 | |
264 rip3 = self.rip # end of while loop | |
265 self.fixCode(fixloc2, imm32(rip1 - rip3)) # Fixup jump to start of while loop | |
266 self.fixCode(fixloc1, imm32(rip3 - rip2)) # Fixup jump out of while loop | |
267 | |
268 elif type(node) is ForStatement: | 159 elif type(node) is ForStatement: |
269 # Initial load of iterator variable: | 160 # Initial load of iterator variable: |
270 self.genexprcode(node.begin) | 161 self.genexprcode(node.begin) |
271 self.genexprcode(node.end) | 162 self.genexprcode(node.end) |
272 # TODO: link reg with variable so that a register is used instead of a variable | |
273 iterreg = node.begin.reg # Get the register used for the loop | |
274 #self.addCode(cmpreg64(iterreg, node.endvalue)) | |
275 rip1 = self.rip | |
276 self.gencode(node.statements) | 163 self.gencode(node.statements) |
277 #self.loadDesignatorInReg(node. | |
278 #self.addCode( addreg64(node.variable, node.increment) ) | |
279 self.addCode(nearjump(0x0)) | |
280 fixloc1 = self.rip - 4 | |
281 rip2 = self.rip | |
282 self.fixCode(fixloc1, imm32(rip1 - rip2)) | |
283 | |
284 self.freereg(node.begin) # Release register used in loop | |
285 self.freereg(node.end) | |
286 Error('No implementation of FOR statement') | 164 Error('No implementation of FOR statement') |
287 | 165 |
288 elif type(node) is AsmCode: | 166 elif type(node) is AsmCode: |
289 def processOperand(op): | 167 def processOperand(op): |
290 if type(op) is list: | 168 if type(op) is list: |
323 # Loop over all designators.. | 201 # Loop over all designators.. |
324 for selector in node.selectors: | 202 for selector in node.selectors: |
325 if type(selector) is Index: | 203 if type(selector) is Index: |
326 # Deref an array index | 204 # Deref an array index |
327 self.genexprcode(selector.index) | 205 self.genexprcode(selector.index) |
328 self.getreg(selector) | |
329 self.addCode( mov(selector.reg, selector.typ.elementType.size) ) | |
330 self.addCode( imulreg64(selector.reg, selector.index.reg ) ) | |
331 self.freereg(selector.index) | |
332 self.addCode(addreg64(node.reg, selector.reg)) | |
333 self.freereg(selector) | 206 self.freereg(selector) |
334 elif type(selector) is Field: | 207 elif type(selector) is Field: |
335 print('Field') | 208 print('Field') |
336 Error('Field not implemented') | 209 Error('Field not implemented') |
337 else: | 210 else: |
338 Error('Unknown selector') | 211 Error('Unknown selector') |
339 else: | 212 else: |
340 Error('Can only gencode for designator with selectors') | 213 Error('Can only gencode for designator with selectors') |
341 | |
342 else: | 214 else: |
343 print('not generating code for {0}'.format(node)) | 215 print('not generating code for {0}'.format(node)) |
344 | 216 |
345 def generateIr(self, ast): | 217 def generateIr(self, context, ast): |
346 """ ir generation front end """ | 218 """ ir generation front end """ |
219 # Create a new context for this code. | |
220 self.context = context | |
347 return self.gencode(ast) | 221 return self.gencode(ast) |
348 | 222 |