annotate python/ppci/frontends/ks/irgenerator.py @ 103:28a35161ef23

Added forgotten ir generator
author windel
date Wed, 26 Dec 2012 10:53:33 +0100
parents
children ed230e947dc6
rev   line source
103
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
1 """
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
2 Generates ir code from ast tree.
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
3 """
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
4
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
5 from .nodes import *
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
6 from ...core.errors import Error
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
7 from ... import core
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
8 from .builtin import real, integer, boolean, char
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
9 #from .assembler import *
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
10
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
11 class KsIrGenerator:
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
12 def __init__(self):
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
13 pass
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
14
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
15 # Code generation functions:
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
16 def genexprcode(self, node):
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
17 """
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
18 Generate code for expressions!
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
19 Recursively evaluates, and ensures a register contains the answer.
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
20 register is an integer register or a floating point reg
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
21 """
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
22 if isinstance(node, Binop):
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
23 """ Handle a binary operation (two arguments) of some kind """
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
24 self.genexprcode(node.a)
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
25 self.genexprcode(node.b)
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
26
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
27 if node.op == 'mod':
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
28 assert(node.typ.isType(integer))
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
29 self.addCode(mov('rax', node.a.reg))
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
30 elif node.op == 'div':
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
31 assert(node.typ.isType(integer))
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
32 self.addCode(mov('rax', node.a.reg))
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
33 elif node.op == '*':
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
34 if node.typ.isType(integer):
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
35 self.addCode(imulreg64(node.a.reg, node.b.reg))
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
36 elif node.op == '+':
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
37 if node.typ.isType(integer):
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
38 self.addCode(addreg64(node.a.reg, node.b.reg))
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
39 elif node.op == '-':
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
40 if node.typ.isType(integer):
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
41 self.addCode(subreg64(node.a.reg, node.b.reg))
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
42 else:
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
43 Error('Unknown Binop {0}'.format(node.op))
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
44
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
45 elif type(node) is Unop:
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
46 if node.op == 'INTTOREAL':
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
47 self.genexprcode(node.a)
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
48 node.reg = node.a.reg
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
49 # TODO use 'FILD' instruction
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
50 freg = 12
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
51 code.append('Unop inttoreal TODO')
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
52 elif node.op == 'ABS':
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
53 if isType(node.typ, real):
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
54 code = [0xD9, 0xE1] # st(0) = fabs st(0)
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
55 Error('ABS error integer')
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
56 elif isType(node.typ, integer):
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
57 code = []
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
58 Error('ABS error integer')
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
59 else:
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
60 Error('ABS error')
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
61 else:
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
62 Error('Unknown Unop {0}'.format(node.op))
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
63
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
64 elif isinstance(node, Designator):
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
65 # dereference, array index. Make sure that the result comes into a register
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
66 if len(node.selectors) > 0:
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
67 self.gencode(node) # Load the pointer into some register
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
68
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
69 # Now we can access the object at location '[node.reg]':
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
70 if node.typ.isType(integer):
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
71 self.addCode( mov(node.reg, [node.reg, 0x0]) )
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
72 else:
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
73 Error('Only integer types implemented')
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
74 else:
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
75 # No selectors, load variable directly
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
76 if node.obj.typ.isType(integer):
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
77 if type(node.obj) is Constant:
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
78 self.genexprcode(node.obj)
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
79 node.reg = node.obj.reg
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
80 else:
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
81 self.getreg(node)
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
82 # Get a register to store the integer value
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
83 if node.obj.isLocal:
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
84 # relative to rbp:
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
85 self.addCode( mov(node.reg, ['rbp', node.obj.offset]) )
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
86 else:
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
87 self.addCode(mov(node.reg, ['RIP', 0x0]))
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
88 self.fixCode(self.rip-4, imm32(node.obj.offset - self.rip))
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
89 else:
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
90 Error('Cannot load variable type {0}'.format(node.typ))
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
91
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
92 elif isinstance(node, Relop):
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
93 # Create a boolean from operands
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
94 # TODO create an alternative for expressions used as conditions.
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
95 self.genexprcode(node.a)
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
96 self.genexprcode(node.b)
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
97
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
98 if node.a.typ.isType(integer):
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
99 self.freereg(node.b)
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
100 else:
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
101 Error('Relop not implemented for {0}'.format(node.a.typ))
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
102
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
103 elif type(node) is Constant:
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
104 if node.typ.isType(integer):
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
105 self.getreg(node)
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
106
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
107 elif type(node) is ProcedureCall:
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
108 if type(node.proc.obj) is BuiltinProcedure:
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
109 # Handle builtin procedures different, these not always call
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
110 # a function, but generate code.
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
111 bi = node.proc.obj
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
112 if bi.name == 'chr':
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
113 arg = node.args[0]
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
114 self.genexprcode(arg)
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
115 # Store character in full width register:
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
116 # TODO: store in char only register
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
117 node.reg = arg.reg
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
118 else:
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
119 Error('Unknown builtin function {0}'.format(bi.name))
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
120 else:
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
121 # Use generic procedure call first
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
122 self.gencode(node)
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
123 # Retrieve result:
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
124 if node.typ.isType(integer):
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
125 # Store result!
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
126 self.getreg(node)
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
127 self.addCode( mov(node.reg, 'rax') )
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
128 else:
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
129 Error('Return type not supported {0}'.format(node.typ))
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
130 else:
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
131 Error('Cannot generate expression code for: {0}'.format(node))
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
132
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
133 def gencode(self, node):
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
134 """ Code generation function for AST nodes """
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
135 if isinstance(node, Module):
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
136 # TODO: recurse!
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
137 return core.Module()
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
138
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
139 elif type(node) is Procedure:
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
140 # calculate offsets for local variables and parameters
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
141 # Variable location relative to 'rbp' register
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
142 variables = node.symtable.getAllLocal(Variable)
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
143 offset = 0
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
144 paramoffset = 16
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
145 for var in variables:
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
146 var.isLocal = True
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
147 if not var.isParameter:
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
148 offset += var.typ.size
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
149 # Offset is negative of rbp in stack frame
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
150 var.offset = -offset
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
151 node.framesize = offset
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
152 # Calculate offsets of parameters relative to rbp register
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
153 for par in reversed(node.typ.parameters):
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
154 pvar = node.symtable.getLocal(Variable, par.name)
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
155 pvar.offset = paramoffset
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
156 paramoffset += pvar.typ.size
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
157
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
158 # code generation
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
159 node.entrypoint = self.rip
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
160 self.addCode(push('rbp'))
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
161 self.addCode(mov('rbp', 'rsp')) # Setup the base pointer
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
162 self.addCode(subreg64('rsp', node.framesize)) # reserve space for locals
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
163 self.gencode(node.block)
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
164 if node.retexpr:
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
165 if node.retexpr.typ.isType(integer):
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
166 self.genexprcode(node.retexpr)
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
167 self.addCode( mov('rax', node.retexpr.reg) )
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
168 self.freereg(node.retexpr)
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
169 else:
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
170 Error('Cannot return this kind yet {0}'.format(node.retexpr.typ))
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
171 self.addCode( addreg64('rsp', node.framesize) )
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
172 self.addCode( pop('rbp') )
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
173 self.addCode( ret() )
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
174 assert(len(self.usedregs) == 0)
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
175
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
176 elif isinstance(node, StatementSequence):
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
177 for s in node.statements:
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
178 self.gencode(s)
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
179
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
180 elif type(node) is ProcedureCall:
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
181 # Prepare parameters on the stack:
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
182 stacksize = 0
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
183 assert(len(node.args) == len(node.proc.typ.parameters))
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
184 for arg, param in zip(node.args, node.proc.typ.parameters):
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
185
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
186 if param.kind == 'value':
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
187 self.genexprcode(arg)
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
188 self.addCode( push(arg.reg) )
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
189 self.freereg( arg )
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
190 stacksize += 8
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
191 else:
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
192 Error('Parameter kind other than value')
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
193
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
194 # Calculate address using designator
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
195 if type(node.proc.obj) is Procedure:
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
196 self.addCode( call(0x0) )
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
197 self.fixCode( self.rip - 4, imm32(node.proc.obj.entrypoint - self.rip))
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
198 elif type(node.proc.obj) is ImportedSymbol:
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
199 # Load the entry point of the import table
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
200 self.getreg(node.proc.obj)
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
201 # Load the address of the procedure:
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
202 self.addCode( mov(node.proc.obj.reg, ['RIP', 0x0]) )
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
203 self.fixCode( self.rip - 4, imm32(node.proc.obj.offset - self.rip) )
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
204 # Call to the address in register:
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
205 self.addCode( call(node.proc.obj.reg) )
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
206 # Free register that holds the address of the object
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
207 self.freereg( node.proc.obj )
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
208 elif type(node.proc.obj) is BuiltinProcedure:
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
209 if node.proc.obj.name == 'chr':
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
210 print('int to char')
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
211 else:
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
212 Error('Unknown builtin function {0}'.format(node.proc.obj.name))
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
213 else:
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
214 Error('Cannot call designator of type {0}'.format(node.proc.obj))
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
215
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
216 # Restore stack (pop all arguments of):
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
217 self.addCode(addreg64('rsp', stacksize))
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
218
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
219 elif type(node) is Assignment:
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
220 if node.lval.typ.isType(integer):
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
221 # TODO if node.rval is Constant of some datatype, move it to mem directly
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
222 self.genexprcode(node.rval) # Calculate the value that has to be stored.
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
223 self.storeRegInDesignator(node.rval.reg, node.lval)
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
224 self.freereg(node.rval)
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
225 else:
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
226 Error('Assignments of other types not implemented')
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
227 # TODO if left and right are designators, do some sort of memcpy.
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
228
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
229 elif type(node) is IfStatement:
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
230 self.genexprcode(node.condition)
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
231 self.addCode( cmpreg64(node.condition.reg, 1) )
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
232 self.freereg(node.condition)
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
233 if node.falsestatement:
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
234 # If with else clause
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
235 self.addCode( nearjump(0x0, condition='NE') ) # if Not Equal jump to false
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
236 rip1 = self.rip
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
237 fixloc1 = self.rip - 4
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
238 self.gencode(node.truestatement)
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
239 self.addCode( nearjump( 0x0 ) ) # jump over false code
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
240 fixloc2 = self.rip - 4
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
241 self.fixCode(fixloc1, imm32(self.rip - rip1))
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
242 rip2 = self.rip
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
243 self.gencode(node.falsestatement)
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
244 self.fixCode(fixloc2, imm32(self.rip - rip2))
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
245 else:
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
246 # If without else clause
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
247 self.addCode( nearjump(0x0, condition='NE') ) # if Not Equal jump to false
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
248 rip1 = self.rip
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
249 fixloc1 = self.rip - 4
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
250 self.gencode(node.truestatement)
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
251 self.fixCode(fixloc1, imm32(self.rip - rip1)) # Fixup near jump over true code.
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
252
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
253 elif isinstance(node, WhileStatement):
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
254 rip1 = self.rip # Store the start of the while loop
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
255 self.genexprcode(node.condition)
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
256 self.addCode( cmpreg64(node.condition.reg, 1) ) # Test condition for true-ness
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
257 self.freereg(node.condition)
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
258 self.addCode( nearjump(0x0, condition='NE') ) # If Not Equal jump over while code AND jump back (fix later)
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
259 fixloc1 = self.rip - 4
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
260 rip2 = self.rip
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
261 self.gencode(node.dostatements)
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
262 self.addCode( nearjump(0x0) ) # JMP to condition, fix exact jump position below
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
263 fixloc2 = self.rip - 4
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
264 rip3 = self.rip # end of while loop
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
265 self.fixCode(fixloc2, imm32(rip1 - rip3)) # Fixup jump to start of while loop
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
266 self.fixCode(fixloc1, imm32(rip3 - rip2)) # Fixup jump out of while loop
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
267
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
268 elif type(node) is ForStatement:
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
269 # Initial load of iterator variable:
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
270 self.genexprcode(node.begin)
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
271 self.genexprcode(node.end)
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
272 # TODO: link reg with variable so that a register is used instead of a variable
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
273 iterreg = node.begin.reg # Get the register used for the loop
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
274 #self.addCode(cmpreg64(iterreg, node.endvalue))
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
275 rip1 = self.rip
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
276 self.gencode(node.statements)
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
277 #self.loadDesignatorInReg(node.
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
278 #self.addCode( addreg64(node.variable, node.increment) )
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
279 self.addCode(nearjump(0x0))
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
280 fixloc1 = self.rip - 4
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
281 rip2 = self.rip
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
282 self.fixCode(fixloc1, imm32(rip1 - rip2))
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
283
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
284 self.freereg(node.begin) # Release register used in loop
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
285 self.freereg(node.end)
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
286 Error('No implementation of FOR statement')
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
287
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
288 elif type(node) is AsmCode:
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
289 def processOperand(op):
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
290 if type(op) is list:
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
291 if type(op[0]) is Variable:
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
292 var = op[0]
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
293 if var.isLocal:
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
294 return ['rbp', var.offset]
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
295 else:
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
296 Error('Can only use local variables in inline assembler')
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
297 return op
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
298 for asmline in node.asmcode:
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
299 opcode, operands = asmline
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
300 operands = [processOperand(opx) for opx in operands]
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
301 print('assembling', opcode, *operands)
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
302 func,nargs = opcodes[opcode]
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
303 code = func(*operands)
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
304 self.addCode(code)
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
305
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
306 elif isinstance(node, EmptyStatement):
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
307 pass
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
308
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
309 elif type(node) is StringConstant:
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
310 self.strings.append(node)
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
311 self.data.append(node.value) # Add string to the data section
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
312
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
313 elif type(node) is Designator:
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
314 if len(node.selectors) > 0:
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
315 self.getreg(node)
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
316 # Load starting address
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
317 if node.obj.isLocal:
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
318 self.addCode( leareg64(node.reg, ['rbp', node.obj.offset]) )
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
319 else:
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
320 # Global variables need to be relocated...
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
321 self.addCode(leareg64(node.reg, ['RIP', 0]))
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
322 self.fixCode(self.rip - 4, imm32(node.obj.offset - self.rip))
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
323 # Loop over all designators..
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
324 for selector in node.selectors:
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
325 if type(selector) is Index:
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
326 # Deref an array index
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
327 self.genexprcode(selector.index)
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
328 self.getreg(selector)
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
329 self.addCode( mov(selector.reg, selector.typ.elementType.size) )
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
330 self.addCode( imulreg64(selector.reg, selector.index.reg ) )
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
331 self.freereg(selector.index)
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
332 self.addCode(addreg64(node.reg, selector.reg))
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
333 self.freereg(selector)
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
334 elif type(selector) is Field:
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
335 print('Field')
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
336 Error('Field not implemented')
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
337 else:
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
338 Error('Unknown selector')
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
339 else:
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
340 Error('Can only gencode for designator with selectors')
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
341
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
342 else:
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
343 print('not generating code for {0}'.format(node))
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
344
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
345 def generateIr(self, ast):
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
346 """ ir generation front end """
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
347 return self.gencode(ast)
28a35161ef23 Added forgotten ir generator
windel
parents:
diff changeset
348