DEADSOFTWARE

685786f19f9af12ff75fdc30ab16801a75cb922d
[dsw-obn.git] / generator.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <stdarg.h>
4 #include <ctype.h>
5 #include <string.h>
6 #include <assert.h>
8 #include "oberon.h"
9 #include "generator.h"
11 #include <libgccjit.h>
13 static void printcontext(oberon_context_t * ctx, char * s)
14 {
15 /*
16 gen_context_t * gen_context = ctx -> gen_context;
17 gcc_jit_context * gcc_context = gen_context -> gcc_context;
18 gcc_jit_block * gcc_block = gen_context -> gcc_block;
20 printf("%s:\n", s);
21 printf(" ctx = %p:\n", ctx);
22 printf(" gctx = %p:\n", gctx);
23 printf(" context = %p:\n", context);
24 printf(" block = %p:\n", block);
25 */
26 }
28 // =======================================================================
29 // ALLOC
30 // =======================================================================
32 void
33 oberon_generator_init_context(oberon_context_t * ctx)
34 {
35 gen_context_t * gen_context = malloc(sizeof *gen_context);
36 memset(gen_context, 0, sizeof *gen_context);
38 gcc_jit_context * gcc_context;
39 gcc_context = gcc_jit_context_acquire();
41 ctx -> gen_context = gen_context;
42 gen_context -> gcc_context = gcc_context;
44 printcontext(ctx, "oberon_generator_init_context");
45 }
47 void
48 oberon_generator_destroy_context(oberon_context_t * ctx)
49 {
50 printcontext(ctx, "oberon_generator_destroy_context");
52 gen_context_t * gen_context = ctx -> gen_context;
53 gcc_jit_context * gcc_context = gen_context -> gcc_context;
55 gcc_jit_context_release(gcc_context);
56 }
58 void
59 oberon_generator_init_type(oberon_context_t * ctx, oberon_type_t * type)
60 {
61 gen_type_t * gen_type = malloc(sizeof *gen_type);
62 memset(gen_type, 0, sizeof *gen_type);
63 type -> gen_type = gen_type;
65 gen_context_t * gen_context = ctx -> gen_context;
66 gcc_jit_context * gcc_context = gen_context -> gcc_context;
68 gcc_jit_type * gcc_type;
69 if(type -> class == OBERON_TYPE_VOID)
70 {
71 gcc_type = gcc_jit_context_get_type(gcc_context, GCC_JIT_TYPE_VOID);
72 }
73 else if(type -> class == OBERON_TYPE_INTEGER)
74 {
75 gcc_type = gcc_jit_context_get_int_type(gcc_context, type -> size, 1);
76 }
77 else if(type -> class == OBERON_TYPE_BOOLEAN)
78 {
79 gcc_type = gcc_jit_context_get_type(gcc_context, GCC_JIT_TYPE_BOOL);
80 }
81 else if(type -> class == OBERON_TYPE_PROCEDURE)
82 {
83 gcc_type = NULL; // not used
84 }
85 else if(type -> class == OBERON_TYPE_ARRAY)
86 {
87 if(type -> dim != 1)
88 {
89 oberon_error(ctx, "multidimension and open arrays not supported");
90 }
92 gen_type_t * gen_base = type -> base -> gen_type;
93 gcc_jit_type * gcc_base = gen_base -> gcc_type;
95 gcc_type = gcc_jit_context_new_array_type(gcc_context, NULL, gcc_base, type -> size);
96 }
97 else
98 {
99 oberon_error(ctx, "oberon_generator_init_type: invalid type class %i", type -> class);
102 gen_type -> gcc_type = gcc_type;
105 void
106 oberon_generator_init_var(oberon_context_t * ctx, oberon_object_t * var)
108 gen_context_t * gen_context = ctx -> gen_context;
109 gen_type_t * gen_type = var -> type -> gen_type;
111 gen_var_t * gen_var = malloc(sizeof *gen_var);
112 memset(gen_var, 0, sizeof *gen_var);
113 var -> gen_var = gen_var;
115 gcc_jit_context * gcc_context = gen_context -> gcc_context;
116 gcc_jit_type * gcc_type = gen_type -> gcc_type;
117 const char * name = var -> name;
119 // TODO var param
120 if(var -> class == OBERON_CLASS_VAR)
122 gen_var -> gcc_lvalue = gcc_jit_context_new_global(
123 gcc_context, NULL, GCC_JIT_GLOBAL_INTERNAL, gcc_type, name
124 );
126 else if(var -> class == OBERON_CLASS_PARAM)
128 gen_var -> gcc_param = gcc_jit_context_new_param(gcc_context, NULL, gcc_type, name);
129 gen_var -> gcc_lvalue = gcc_jit_param_as_lvalue(gen_var -> gcc_param);
131 else
133 oberon_error(ctx, "oberon_generator_init_var: invalid class %i", var -> class);
137 void
138 oberon_generator_init_proc(oberon_context_t * ctx, oberon_object_t * proc)
140 assert(proc -> class == OBERON_CLASS_PROC);
142 gen_context_t * gen_context = ctx -> gen_context;
143 gcc_jit_context * gcc_context = gen_context -> gcc_context;
145 gen_proc_t * gen_proc = malloc(sizeof *gen_proc);
146 memset(gen_proc, 0, sizeof *gen_proc);
147 proc -> gen_proc = gen_proc;
149 const char * name = proc -> name;
150 gen_type_t * gen_result_type = proc -> type -> base -> gen_type;
151 gcc_jit_type * result_type = gen_result_type -> gcc_type;
153 /* Строим список параметров */
154 int num_param = proc -> type -> num_decl;
155 oberon_object_t * o = proc -> type -> decl;
156 gcc_jit_param * params[num_param];
157 for(int i = 0; i < num_param; i++)
159 gen_var_t * param_var = o -> gen_var;
160 params[i] = param_var -> gcc_param;
161 o = o -> next;
164 gcc_jit_function * gcc_func;
165 gcc_func = gcc_jit_context_new_function(
166 gcc_context, NULL, GCC_JIT_FUNCTION_EXPORTED, result_type, name, num_param, params, 0
167 );
169 gen_proc -> gcc_func = gcc_func;
172 // =======================================================================
173 // GENERATOR
174 // =======================================================================
176 static gcc_jit_rvalue * rvalue_from_expr(oberon_context_t * ctx, oberon_expr_t * expr);
178 void
179 oberon_generate_begin_module(oberon_context_t * ctx)
181 printcontext(ctx, "oberon_generate_begin_module");
183 gen_context_t * gen_context = ctx -> gen_context;
184 gcc_jit_context * gcc_context = gen_context -> gcc_context;
186 gcc_jit_type * void_type = gcc_jit_context_get_type(gcc_context, GCC_JIT_TYPE_VOID);
187 gcc_jit_function * func = gcc_jit_context_new_function(
188 gcc_context, NULL, GCC_JIT_FUNCTION_EXPORTED, void_type, "BEGIN", 0, NULL, 0
189 );
190 gcc_jit_block * gcc_block = gcc_jit_function_new_block(func, NULL);
192 gen_context -> gcc_block = gcc_block;
195 void
196 oberon_generate_end_module(oberon_context_t * ctx)
198 printcontext(ctx, "oberon_generate_end_module");
200 gen_context_t * gen_context = ctx -> gen_context;
201 gcc_jit_block * gcc_block = gen_context -> gcc_block;
203 gcc_jit_block_end_with_void_return(gcc_block, NULL);
205 gen_context -> gcc_block = NULL;
208 void
209 oberon_generate_begin_proc(oberon_context_t * ctx, oberon_object_t * proc)
211 gen_context_t * gen_context = ctx -> gen_context;
212 gen_proc_t * gen_proc = proc -> gen_proc;
214 gcc_jit_function * func = gen_proc -> gcc_func;
215 gcc_jit_block * gcc_block = gcc_jit_function_new_block(func, NULL);
217 // TODO make stack for block
218 gen_context -> gcc_block = gcc_block;
221 void
222 oberon_generate_call_proc(oberon_context_t * ctx, oberon_expr_t * desig)
224 gen_context_t * gen_context = ctx -> gen_context;
225 gcc_jit_block * block = gen_context -> gcc_block;
227 gcc_jit_rvalue * return_value;
228 return_value = rvalue_from_expr(ctx, desig);
229 gcc_jit_block_add_eval(block, NULL, return_value);
232 void
233 oberon_generate_end_proc(oberon_context_t * ctx)
235 gen_context_t * gen_context = ctx -> gen_context;
236 gen_context -> gcc_block = NULL;
239 void
240 oberon_generate_return(oberon_context_t * ctx, oberon_expr_t * expr)
242 gen_context_t * gen_context = ctx -> gen_context;
243 gcc_jit_block * gcc_block = gen_context -> gcc_block;
245 if(expr == NULL)
247 gcc_jit_block_end_with_void_return(gcc_block, NULL);
249 else
251 gcc_jit_rvalue * r = rvalue_from_expr(ctx, expr);
252 gcc_jit_block_end_with_return(gcc_block, NULL, r);
256 static gcc_jit_lvalue *
257 lvalue_from_expr(oberon_context_t *ctx, oberon_expr_t * expr)
259 gcc_jit_lvalue * left;
260 oberon_item_t * item;
262 if(expr -> is_item)
264 item = (oberon_item_t *) expr;
265 if(item -> mode != MODE_VAR)
267 oberon_error(ctx, "invalid lvalue expression");
269 gen_var_t * gen_var = item -> var -> gen_var;
270 left = gen_var -> gcc_lvalue;
272 else
274 oberon_error(ctx, "invalid lvalue expression");
277 return left;
280 static gcc_jit_rvalue *
281 rvalue_from_item(oberon_context_t * ctx, oberon_item_t * item)
283 gen_context_t * gen_context = ctx -> gen_context;
284 gcc_jit_context * gcc_context = gen_context -> gcc_context;
286 gcc_jit_rvalue * right;
287 if(item -> mode == MODE_VAR)
289 assert(item -> var -> class == OBERON_CLASS_VAR
290 || item -> var -> class == OBERON_CLASS_PARAM);
291 gen_var_t * gen_var = item -> var -> gen_var;
292 right = gcc_jit_lvalue_as_rvalue(gen_var -> gcc_lvalue);
294 else if(item -> mode == MODE_INTEGER)
296 gcc_jit_type * int_type = gcc_jit_context_get_type(gcc_context, GCC_JIT_TYPE_INT);
297 right = gcc_jit_context_new_rvalue_from_int(gcc_context, int_type, item -> integer);
299 else if(item -> mode == MODE_BOOLEAN)
301 gcc_jit_type * bool_type = gcc_jit_context_get_type(gcc_context, GCC_JIT_TYPE_BOOL);
302 if(item -> boolean)
304 right = gcc_jit_context_one(gcc_context, bool_type);
306 else
308 right = gcc_jit_context_zero(gcc_context, bool_type);
311 else if(item -> mode == MODE_CALL)
313 assert(item -> var -> class == OBERON_CLASS_PROC);
315 gen_proc_t * gen_proc = item -> var -> gen_proc;
317 int num_args = item -> num_args;
318 gcc_jit_rvalue *args[num_args];
320 oberon_expr_t * expr = item -> args;
321 for(int i = 0; i < num_args; i++)
323 args[i] = rvalue_from_expr(ctx, expr);
324 expr = expr -> next;
327 gcc_jit_function * func = gen_proc -> gcc_func;
328 right = gcc_jit_context_new_call(
329 gcc_context, NULL, func, num_args, args
330 );
332 else
334 oberon_error(ctx, "oberon_generate_push: invalid mode %i", item -> mode);
337 return right;
340 struct {
341 int type; // 0 - unary, 1 - binary, 2 - comp
342 union {
343 enum gcc_jit_unary_op unary_op;
344 enum gcc_jit_binary_op binary_op;
345 enum gcc_jit_comparison comp_op;
346 };
347 } op_table[] = {
348 { 0, .unary_op = GCC_JIT_UNARY_OP_LOGICAL_NEGATE },
349 { 0, .unary_op = GCC_JIT_UNARY_OP_MINUS },
351 { 1, .binary_op = GCC_JIT_BINARY_OP_PLUS },
352 { 1, .binary_op = GCC_JIT_BINARY_OP_MINUS },
353 { 1, .binary_op = GCC_JIT_BINARY_OP_DIVIDE },
354 { 1, .binary_op = GCC_JIT_BINARY_OP_MODULO },
355 { 1, .binary_op = GCC_JIT_BINARY_OP_LOGICAL_AND },
356 { 1, .binary_op = GCC_JIT_BINARY_OP_LOGICAL_OR },
358 { 2, .comp_op = GCC_JIT_COMPARISON_EQ },
359 { 2, .comp_op = GCC_JIT_COMPARISON_NE },
360 { 2, .comp_op = GCC_JIT_COMPARISON_LT },
361 { 2, .comp_op = GCC_JIT_COMPARISON_LE },
362 { 2, .comp_op = GCC_JIT_COMPARISON_GT },
363 { 2, .comp_op = GCC_JIT_COMPARISON_GE }
364 };
366 static gcc_jit_rvalue *
367 rvalue_from_operator(oberon_context_t * ctx, oberon_oper_t * operator)
369 gcc_jit_rvalue * right;
371 gen_context_t * gen_context = ctx -> gen_context;
372 gen_type_t * gen_type = operator -> result -> gen_type;
373 gcc_jit_context * gcc_context = gen_context -> gcc_context;
374 gcc_jit_type * result_type = gen_type -> gcc_type;
376 int expr_type = op_table[operator -> op].type;
377 if(expr_type == 0)
379 enum gcc_jit_unary_op op = op_table[operator -> op].unary_op;
380 gcc_jit_rvalue * l = rvalue_from_expr(ctx, operator -> left);
381 right = gcc_jit_context_new_unary_op(gcc_context, NULL, op, result_type, l);
383 else if(expr_type == 1)
385 enum gcc_jit_unary_op op = op_table[operator -> op].binary_op;
386 gcc_jit_rvalue * l = rvalue_from_expr(ctx, operator -> left);
387 gcc_jit_rvalue * r = rvalue_from_expr(ctx, operator -> right);
388 right = gcc_jit_context_new_binary_op(gcc_context, NULL, op, result_type, l, r);
390 else if(expr_type == 2)
392 enum gcc_jit_comparison op = op_table[operator -> op].comp_op;
393 gcc_jit_rvalue * l = rvalue_from_expr(ctx, operator -> left);
394 gcc_jit_rvalue * r = rvalue_from_expr(ctx, operator -> right);
395 right = gcc_jit_context_new_comparison(gcc_context, NULL, op, l, r);
397 else
399 oberon_error(ctx, "rvalue_from_operator: wat");
402 return right;
405 static gcc_jit_rvalue *
406 rvalue_from_expr(oberon_context_t * ctx, oberon_expr_t * expr)
408 gcc_jit_rvalue * right;
410 if(expr -> is_item)
412 oberon_item_t * item = (oberon_item_t *) expr;
413 right = rvalue_from_item(ctx, item);
415 else
417 oberon_oper_t * operator = (oberon_oper_t *) expr;
418 right = rvalue_from_operator(ctx, operator);
421 return right;
424 void
425 oberon_generate_assign(oberon_context_t * ctx, oberon_expr_t * src, oberon_expr_t * dst)
427 gcc_jit_lvalue * left;
428 left = lvalue_from_expr(ctx, dst);
430 gcc_jit_rvalue * right;
431 right = rvalue_from_expr(ctx, src);
433 gen_context_t * gen_context = ctx -> gen_context;
434 gcc_jit_block * gcc_block = gen_context -> gcc_block;
435 gcc_jit_block_add_assignment(gcc_block, NULL, left, right);
438 void
439 oberon_generate_code(oberon_context_t * ctx)
441 gen_context_t * gen_context = ctx -> gen_context;
442 gcc_jit_context * gcc_context = gen_context -> gcc_context;
444 gcc_jit_result * gcc_result;
445 gcc_result = gcc_jit_context_compile(gcc_context);
447 gen_context -> gcc_result = gcc_result;
448 ctx -> mod -> begin = gcc_jit_result_get_code(gcc_result, "BEGIN");