annotate python/ppci/backends/codegenerator.py @ 99:6efbeb903777

movage
author windel
date Mon, 24 Dec 2012 15:03:30 +0100
parents a350055d6119
children
rev   line source
1
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
1 """
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
2 Code generation for 64 bits intel processors
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
3 """
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
4
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
5 from .nodes import *
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
6 from .errors import Error
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
7 from .builtin import real, integer, boolean, char
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
8 from .assembler import *
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
9
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
10 class CodeGenerator:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
11 def __init__(self):
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
12 self.strings = []
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
13 self.initialize()
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
14 def initialize(self):
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
15 # Register descriptors:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
16 self.freeregs = 'r8,r9,r10,r11,r12,r13,r14,r15'.split(',')
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
17 self.usedregs = []
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
18 # Members to accumulate the result into:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
19 # The result is an image of bytecode and global variable space.
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
20 # Global variables a referenced by RIP relative addressing.
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
21 self.image = []
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
22 self.rip = 0 # The current instruction pointer location.
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
23 # TODO: backpatch list here?
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
24
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
25 # Functions to modify the code image
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
26 def addCode(self, code):
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
27 assert(type(code) is list)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
28 self.image += code
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
29 self.rip += len(code)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
30 def fixCode(self, position, code):
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
31 self.image[position:position+len(code)] = code
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
32 def align(self, b):
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
33 while (self.rip % b) != 0:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
34 self.addCode([0])
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
35
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
36 def saveAllRegisters(self):
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
37 regs = list(self.usedregs.keys())
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
38 for reg in regs:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
39 code += self.saveRegister(reg)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
40
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
41 def saveRegister(self, reg):
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
42 code = []
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
43 if reg in self.usedregs.keys():
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
44 code.append('mov {0}, {1}'.format(self.usedregs[reg], reg))
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
45 del self.usedregs[reg]
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
46 self.freeregs.append(reg)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
47
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
48 def getreg(self, node):
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
49 """ acquire a working register for a certain node."""
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
50 # Temporary register bypass action:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
51 if len(self.freeregs) > 0:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
52 reg = self.freeregs.pop(0)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
53 self.usedregs.append(reg)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
54 else:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
55 Error('No more free regs')
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
56 node.reg = reg
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
57
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
58 def freereg(self, node):
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
59 reg = node.reg
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
60 node.reg = None
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
61 self.freeregs.append(reg)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
62 self.usedregs.remove(reg)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
63
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
64 # Helpers to load and retrieve designated objects:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
65 def storeRegInDesignator(self, reg, designator):
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
66 assert(type(reg) is str)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
67 assert(type(designator) is Designator)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
68 if len(designator.selectors) > 0:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
69 self.gencode( designator ) # Load the pointer into some register
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
70 self.addCode( mov([designator.reg, 0x0], reg) )
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
71 self.freereg( designator )
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
72 else:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
73 if designator.obj.isLocal:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
74 # Relative from rbp register
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
75 mem = ['rbp', designator.obj.offset]
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
76 self.addCode( mov(mem, reg) )
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
77 else:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
78 # Relative from RIP after move
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
79 self.addCode( mov(['RIP', 0x0], reg) )
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
80 self.fixCode(self.rip - 4, imm32(designator.obj.offset - self.rip) )
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
81
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
82 # Code generation functions:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
83 def genexprcode(self, node):
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
84 """
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
85 Generate code for expressions!
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
86 Recursively evaluates, and ensures a register contains the answer.
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
87 register is an integer register or a floating point reg
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
88 """
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
89 if isinstance(node, Binop):
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
90 """ Handle a binary operation (two arguments) of some kind """
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
91 self.genexprcode(node.a)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
92 self.genexprcode(node.b)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
93
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
94 if node.op == 'mod':
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
95 assert(node.typ.isType(integer))
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
96 self.addCode(mov('rax', node.a.reg))
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
97 self.addCode(xorreg64('rdx', 'rdx')) # Extend divided number with zeros
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
98 self.addCode(idivreg64(node.b.reg)) # divide rdx:rax with reg
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
99 node.reg = node.a.reg
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
100 self.freereg(node.b) # give up register that contains b
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
101 self.addCode(mov(node.reg, 'rdx')) # move remainder into result
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
102 elif node.op == 'div':
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
103 assert(node.typ.isType(integer))
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
104 self.addCode(mov('rax', node.a.reg))
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
105 self.addCode(xorreg64('rdx', 'rdx')) # Extend divided number with zeros
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
106 self.addCode(idivreg64(node.b.reg)) # divide rdx:rax with reg
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
107 node.reg = node.a.reg
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
108 self.freereg(node.b) # give up register that contains b
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
109 self.addCode(mov(node.reg, 'rax')) # move result into reg
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
110 elif node.op == '*':
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
111 if node.typ.isType(integer):
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
112 self.addCode(imulreg64(node.a.reg, node.b.reg))
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
113 node.reg = node.a.reg
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
114 self.freereg(node.b)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
115 else:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
116 Error('{0} for * not implemented'.format(node.typ))
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
117 elif node.op == '+':
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
118 if node.typ.isType(integer):
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
119 self.addCode(addreg64(node.a.reg, node.b.reg))
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
120 node.reg = node.a.reg
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
121 self.freereg(node.b)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
122 else:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
123 Error('{0} for + not implemented'.format(node.typ))
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
124 elif node.op == '-':
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
125 if node.typ.isType(integer):
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
126 self.addCode(subreg64(node.a.reg, node.b.reg))
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
127 node.reg = node.a.reg
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
128 self.freereg(node.b)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
129 else:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
130 Error('{0} for - not implemented'.format(node.typ))
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
131 else:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
132 Error('Unknown Binop {0}'.format(node.op))
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
133
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
134 elif type(node) is Unop:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
135 if node.op == 'INTTOREAL':
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
136 self.genexprcode(node.a)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
137 node.reg = node.a.reg
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
138 # TODO use 'FILD' instruction
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
139 freg = 12
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
140 code.append('Unop inttoreal TODO')
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
141 elif node.op == 'ABS':
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
142 if isType(node.typ, real):
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
143 code = [0xD9, 0xE1] # st(0) = fabs st(0)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
144 Error('ABS error integer')
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
145 elif isType(node.typ, integer):
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
146 code = []
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
147 Error('ABS error integer')
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
148 else:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
149 Error('ABS error')
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
150 else:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
151 Error('Unknown Unop {0}'.format(node.op))
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
152
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
153 elif isinstance(node, Designator):
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
154 # dereference, array index. Make sure that the result comes into a register
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
155 if len(node.selectors) > 0:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
156 self.gencode(node) # Load the pointer into some register
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
157
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
158 # Now we can access the object at location '[node.reg]':
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
159 if node.typ.isType(integer):
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
160 self.addCode( mov(node.reg, [node.reg, 0x0]) )
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
161 else:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
162 Error('Only integer types implemented')
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
163 else:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
164 # No selectors, load variable directly
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
165 if node.obj.typ.isType(integer):
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
166 if type(node.obj) is Constant:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
167 self.genexprcode(node.obj)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
168 node.reg = node.obj.reg
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
169 else:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
170 self.getreg(node)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
171 # Get a register to store the integer value
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
172 if node.obj.isLocal:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
173 # relative to rbp:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
174 self.addCode( mov(node.reg, ['rbp', node.obj.offset]) )
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
175 else:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
176 self.addCode(mov(node.reg, ['RIP', 0x0]))
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
177 self.fixCode(self.rip-4, imm32(node.obj.offset - self.rip))
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
178 else:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
179 Error('Cannot load variable type {0}'.format(node.typ))
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
180
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
181 elif isinstance(node, Relop):
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
182 # Create a boolean from operands
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
183 # TODO create an alternative for expressions used as conditions.
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
184 self.genexprcode(node.a)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
185 self.genexprcode(node.b)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
186
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
187 if node.a.typ.isType(integer):
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
188 instructions = {'<': 'L', '>': 'G', '<>': 'NE', '>=': 'GE', '<=': 'LE', '=':'E'}
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
189 if not node.relop in instructions.keys():
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
190 Error('Unimplemented relop: '+str(node.relop))
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
191 instr = instructions[node.relop]
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
192
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
193 node.reg = node.a.reg
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
194 self.addCode( cmpreg64(node.a.reg, node.b.reg) )
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
195 self.addCode( shortjump(0x0, condition=instr) ) # jump over 0 code and jmp
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
196 fixloc1 = self.rip - 1
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
197 rip1 = self.rip
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
198 self.addCode( xorreg64(node.reg, node.reg) )
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
199 self.addCode( shortjump(0x0) ) # Jump over 1 code
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
200 fixloc2 = self.rip - 1
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
201 self.fixCode(fixloc1, imm8(self.rip - rip1))
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
202 rip2 = self.rip
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
203 self.addCode( xorreg64(node.reg, node.reg) )
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
204 self.addCode( increg64(node.reg) )
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
205 self.fixCode(fixloc2, imm8(self.rip - rip2))
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
206
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
207 self.freereg(node.b)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
208 else:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
209 Error('Relop not implemented for {0}'.format(node.a.typ))
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
210
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
211 elif type(node) is Constant:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
212 if node.typ.isType(integer):
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
213 self.getreg(node)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
214 self.addCode(mov(node.reg, node.value))
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
215 elif node.typ.isType(real):
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
216 code += self.getreg(node)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
217 Error('TODO: get real reg')
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
218 # TODO: get a fixed point reg, and load the variable in there
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
219 else:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
220 Error('Howto generate code for {0}?'.format(node))
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
221
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
222 elif type(node) is ProcedureCall:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
223 if type(node.proc.obj) is BuiltinProcedure:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
224 # Handle builtin procedures different, these not always call
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
225 # a function, but generate code.
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
226 bi = node.proc.obj
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
227 if bi.name == 'chr':
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
228 arg = node.args[0]
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
229 self.genexprcode(arg)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
230 # Store character in full width register:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
231 # TODO: store in char only register
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
232 node.reg = arg.reg
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
233 else:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
234 Error('Unknown builtin function {0}'.format(bi.name))
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
235 else:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
236 # Use generic procedure call first
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
237 self.gencode(node)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
238 # Retrieve result:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
239 if node.typ.isType(integer):
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
240 # Store result!
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
241 self.getreg(node)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
242 self.addCode( mov(node.reg, 'rax') )
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
243 else:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
244 Error('Return type not supported {0}'.format(node.typ))
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
245 else:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
246 Error('Cannot generate expression code for: {0}'.format(node))
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
247
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
248 def gencode(self, node):
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
249 """ Code generation function for AST nodes """
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
250 if isinstance(node, Module):
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
251 # for all imports make a list of pointer to the actual procedures:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
252 for imp in node.imports:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
253 imp.offset = self.rip
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
254 self.addCode( [0x0]*8 )
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
255 # global variable storage allocation
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
256 variables = node.symtable.getAllLocal(Variable)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
257 for var in variables:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
258 var.isLocal = False
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
259 var.offset = self.rip
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
260 self.addCode( [0x00] * var.typ.size ) # TODO initial values here?
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
261 self.align(8)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
262 # TODO: mark end of data and start of code inside image
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
263 # TODO: round data to page size to enable protection by loader.
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
264 # Procedure code generation:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
265 procedures = node.symtable.getAllLocal(Procedure)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
266 node.procs = procedures
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
267 for proc in procedures:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
268 self.gencode(proc)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
269 # Module init code:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
270 node.initcodeentry = self.rip
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
271 self.gencode(node.initcode)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
272 self.addCode( ret() )
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
273 # TODO: how to return from module init code? far return??
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
274
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
275 elif type(node) is Procedure:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
276 # calculate offsets for local variables and parameters
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
277 # Variable location relative to 'rbp' register
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
278 variables = node.symtable.getAllLocal(Variable)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
279 offset = 0
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
280 paramoffset = 16
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
281 for var in variables:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
282 var.isLocal = True
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
283 if not var.isParameter:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
284 offset += var.typ.size
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
285 # Offset is negative of rbp in stack frame
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
286 var.offset = -offset
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
287 node.framesize = offset
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
288 # Calculate offsets of parameters relative to rbp register
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
289 for par in reversed(node.typ.parameters):
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
290 pvar = node.symtable.getLocal(Variable, par.name)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
291 pvar.offset = paramoffset
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
292 paramoffset += pvar.typ.size
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
293
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
294 # code generation
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
295 node.entrypoint = self.rip
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
296 self.addCode(push('rbp'))
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
297 self.addCode(mov('rbp', 'rsp')) # Setup the base pointer
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
298 self.addCode(subreg64('rsp', node.framesize)) # reserve space for locals
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
299 self.gencode(node.block)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
300 if node.retexpr:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
301 if node.retexpr.typ.isType(integer):
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
302 self.genexprcode(node.retexpr)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
303 self.addCode( mov('rax', node.retexpr.reg) )
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
304 self.freereg(node.retexpr)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
305 else:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
306 Error('Cannot return this kind yet {0}'.format(node.retexpr.typ))
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
307 self.addCode( addreg64('rsp', node.framesize) )
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
308 self.addCode( pop('rbp') )
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
309 self.addCode( ret() )
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
310 assert(len(self.usedregs) == 0)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
311
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
312 elif isinstance(node, StatementSequence):
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
313 for s in node.statements:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
314 self.gencode(s)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
315
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
316 elif type(node) is ProcedureCall:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
317 # Prepare parameters on the stack:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
318 stacksize = 0
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
319 assert(len(node.args) == len(node.proc.typ.parameters))
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
320 for arg, param in zip(node.args, node.proc.typ.parameters):
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
321
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
322 if param.kind == 'value':
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
323 self.genexprcode(arg)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
324 self.addCode( push(arg.reg) )
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
325 self.freereg( arg )
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
326 stacksize += 8
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
327 else:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
328 Error('Parameter kind other than value')
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
329
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
330 # Calculate address using designator
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
331 if type(node.proc.obj) is Procedure:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
332 self.addCode( call(0x0) )
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
333 self.fixCode( self.rip - 4, imm32(node.proc.obj.entrypoint - self.rip))
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
334 elif type(node.proc.obj) is ImportedSymbol:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
335 # Load the entry point of the import table
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
336 self.getreg(node.proc.obj)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
337 # Load the address of the procedure:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
338 self.addCode( mov(node.proc.obj.reg, ['RIP', 0x0]) )
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
339 self.fixCode( self.rip - 4, imm32(node.proc.obj.offset - self.rip) )
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
340 # Call to the address in register:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
341 self.addCode( call(node.proc.obj.reg) )
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
342 # Free register that holds the address of the object
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
343 self.freereg( node.proc.obj )
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
344 elif type(node.proc.obj) is BuiltinProcedure:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
345 if node.proc.obj.name == 'chr':
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
346 print('int to char')
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
347 else:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
348 Error('Unknown builtin function {0}'.format(node.proc.obj.name))
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
349 else:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
350 Error('Cannot call designator of type {0}'.format(node.proc.obj))
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
351
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
352 # Restore stack (pop all arguments of):
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
353 self.addCode(addreg64('rsp', stacksize))
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
354
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
355 elif type(node) is Assignment:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
356 if node.lval.typ.isType(integer):
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
357 # TODO if node.rval is Constant of some datatype, move it to mem directly
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
358 self.genexprcode(node.rval) # Calculate the value that has to be stored.
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
359 self.storeRegInDesignator(node.rval.reg, node.lval)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
360 self.freereg(node.rval)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
361 else:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
362 Error('Assignments of other types not implemented')
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
363 # TODO if left and right are designators, do some sort of memcpy.
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
364
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
365 elif type(node) is IfStatement:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
366 self.genexprcode(node.condition)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
367 self.addCode( cmpreg64(node.condition.reg, 1) )
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
368 self.freereg(node.condition)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
369 if node.falsestatement:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
370 # If with else clause
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
371 self.addCode( nearjump(0x0, condition='NE') ) # if Not Equal jump to false
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
372 rip1 = self.rip
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
373 fixloc1 = self.rip - 4
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
374 self.gencode(node.truestatement)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
375 self.addCode( nearjump( 0x0 ) ) # jump over false code
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
376 fixloc2 = self.rip - 4
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
377 self.fixCode(fixloc1, imm32(self.rip - rip1))
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
378 rip2 = self.rip
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
379 self.gencode(node.falsestatement)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
380 self.fixCode(fixloc2, imm32(self.rip - rip2))
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
381 else:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
382 # If without else clause
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
383 self.addCode( nearjump(0x0, condition='NE') ) # if Not Equal jump to false
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
384 rip1 = self.rip
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
385 fixloc1 = self.rip - 4
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
386 self.gencode(node.truestatement)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
387 self.fixCode(fixloc1, imm32(self.rip - rip1)) # Fixup near jump over true code.
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
388
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
389 elif isinstance(node, WhileStatement):
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
390 rip1 = self.rip # Store the start of the while loop
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
391 self.genexprcode(node.condition)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
392 self.addCode( cmpreg64(node.condition.reg, 1) ) # Test condition for true-ness
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
393 self.freereg(node.condition)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
394 self.addCode( nearjump(0x0, condition='NE') ) # If Not Equal jump over while code AND jump back (fix later)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
395 fixloc1 = self.rip - 4
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
396 rip2 = self.rip
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
397 self.gencode(node.dostatements)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
398 self.addCode( nearjump(0x0) ) # JMP to condition, fix exact jump position below
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
399 fixloc2 = self.rip - 4
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
400 rip3 = self.rip # end of while loop
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
401 self.fixCode(fixloc2, imm32(rip1 - rip3)) # Fixup jump to start of while loop
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
402 self.fixCode(fixloc1, imm32(rip3 - rip2)) # Fixup jump out of while loop
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
403
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
404 elif type(node) is ForStatement:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
405 # Initial load of iterator variable:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
406 self.genexprcode(node.begin)
4
0d5ef85b8698 Improved link between ast viewer and code edit
windel-eee
parents: 1
diff changeset
407 self.genexprcode(node.end)
0d5ef85b8698 Improved link between ast viewer and code edit
windel-eee
parents: 1
diff changeset
408 # TODO: link reg with variable so that a register is used instead of a variable
0d5ef85b8698 Improved link between ast viewer and code edit
windel-eee
parents: 1
diff changeset
409 iterreg = node.begin.reg # Get the register used for the loop
0d5ef85b8698 Improved link between ast viewer and code edit
windel-eee
parents: 1
diff changeset
410 #self.addCode(cmpreg64(iterreg, node.endvalue))
1
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
411 rip1 = self.rip
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
412 self.gencode(node.statements)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
413 #self.loadDesignatorInReg(node.
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
414 #self.addCode( addreg64(node.variable, node.increment) )
4
0d5ef85b8698 Improved link between ast viewer and code edit
windel-eee
parents: 1
diff changeset
415 self.addCode(nearjump(0x0))
0d5ef85b8698 Improved link between ast viewer and code edit
windel-eee
parents: 1
diff changeset
416 fixloc1 = self.rip - 4
0d5ef85b8698 Improved link between ast viewer and code edit
windel-eee
parents: 1
diff changeset
417 rip2 = self.rip
0d5ef85b8698 Improved link between ast viewer and code edit
windel-eee
parents: 1
diff changeset
418 self.fixCode(fixloc1, imm32(rip1 - rip2))
0d5ef85b8698 Improved link between ast viewer and code edit
windel-eee
parents: 1
diff changeset
419
0d5ef85b8698 Improved link between ast viewer and code edit
windel-eee
parents: 1
diff changeset
420 self.freereg(node.begin) # Release register used in loop
0d5ef85b8698 Improved link between ast viewer and code edit
windel-eee
parents: 1
diff changeset
421 self.freereg(node.end)
1
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
422 Error('No implementation of FOR statement')
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
423
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
424 elif type(node) is AsmCode:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
425 def processOperand(op):
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
426 if type(op) is list:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
427 if type(op[0]) is Variable:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
428 var = op[0]
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
429 if var.isLocal:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
430 return ['rbp', var.offset]
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
431 else:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
432 Error('Can only use local variables in inline assembler')
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
433 return op
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
434 for asmline in node.asmcode:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
435 opcode, operands = asmline
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
436 operands = [processOperand(opx) for opx in operands]
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
437 print('assembling', opcode, *operands)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
438 func,nargs = opcodes[opcode]
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
439 code = func(*operands)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
440 self.addCode(code)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
441
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
442 elif isinstance(node, EmptyStatement):
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
443 pass
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
444
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
445
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
446 elif type(node) is StringConstant:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
447 self.strings.append(node)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
448 self.data.append(node.value) # Add string to the data section
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
449
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
450 elif type(node) is Designator:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
451 if len(node.selectors) > 0:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
452 self.getreg(node)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
453 # Load starting address
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
454 if node.obj.isLocal:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
455 self.addCode( leareg64(node.reg, ['rbp', node.obj.offset]) )
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
456 else:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
457 # Global variables need to be relocated...
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
458 self.addCode(leareg64(node.reg, ['RIP', 0]))
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
459 self.fixCode(self.rip - 4, imm32(node.obj.offset - self.rip))
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
460 # Loop over all designators..
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
461 for selector in node.selectors:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
462 if type(selector) is Index:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
463 # Deref an array index
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
464 self.genexprcode(selector.index)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
465 self.getreg(selector)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
466 self.addCode( mov(selector.reg, selector.typ.elementType.size) )
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
467 self.addCode( imulreg64(selector.reg, selector.index.reg ) )
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
468 self.freereg(selector.index)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
469 self.addCode(addreg64(node.reg, selector.reg))
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
470 self.freereg(selector)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
471 elif type(selector) is Field:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
472 print('Field')
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
473 Error('Field not implemented')
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
474 else:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
475 Error('Unknown selector')
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
476 else:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
477 Error('Can only gencode for designator with selectors')
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
478
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
479 else:
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
480 print('not generating code for {0}'.format(node))
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
481
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
482 def generatecode(self, ast):
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
483 """ code generation front end """
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
484 self.initialize()
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
485 self.gencode(ast)
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
486 ast.image = self.image
92df07bc2081 Initial import of compiler
windel
parents:
diff changeset
487