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