DEADSOFTWARE

07e7bc470ee1b1fb9a337810e695fce530bf16d3
[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 /*
14 * oberon_object_t -> gen_var == gcc_jit_lvalue;
15 * oberon_type_t -> gen_type == gcc_jit_type;
16 * oberon_context_t -> gen_context == gen_context_t;
17 */
19 typedef struct
20 {
21 gcc_jit_context * gcc_context;
22 gcc_jit_block * gcc_block;
23 gcc_jit_result * gcc_result;
24 } gen_context_t;
26 static void printcontext(oberon_context_t * ctx, char * s)
27 {
28 /*
29 gen_context_t * gen_context = ctx -> gen_context;
30 gcc_jit_context * gcc_context = gen_context -> gcc_context;
31 gcc_jit_block * gcc_block = gen_context -> gcc_block;
33 printf("%s:\n", s);
34 printf(" ctx = %p:\n", ctx);
35 printf(" gctx = %p:\n", gctx);
36 printf(" context = %p:\n", context);
37 printf(" block = %p:\n", block);
38 */
39 }
41 // =======================================================================
42 // ALLOC
43 // =======================================================================
45 void
46 oberon_generator_init_context(oberon_context_t * ctx)
47 {
48 gen_context_t * gen_context = malloc(sizeof *gen_context);
49 memset(gen_context, 0, sizeof *gen_context);
51 gcc_jit_context * gcc_context;
52 gcc_context = gcc_jit_context_acquire();
54 ctx -> gen_context = gen_context;
55 gen_context -> gcc_context = gcc_context;
57 printcontext(ctx, "oberon_generator_init_context");
58 }
60 void
61 oberon_generator_destroy_context(oberon_context_t * ctx)
62 {
63 printcontext(ctx, "oberon_generator_destroy_context");
65 gen_context_t * gen_context = ctx -> gen_context;
66 gcc_jit_context * gcc_context = gen_context -> gcc_context;
68 gcc_jit_context_release(gcc_context);
69 }
71 void
72 oberon_generator_init_type(oberon_context_t * ctx, oberon_type_t * type)
73 {
74 printcontext(ctx, "oberon_generator_init_type");
76 gen_context_t * gen_context = ctx -> gen_context;
77 gcc_jit_context * gcc_context = gen_context -> gcc_context;
79 gcc_jit_type * gen_type;
80 if(type -> class == OBERON_TYPE_INTEGER)
81 {
82 gen_type = gcc_jit_context_get_int_type(gcc_context, type -> size, 1);
83 }
84 else if(type -> class == OBERON_TYPE_BOOLEAN)
85 {
86 gen_type = gcc_jit_context_get_type(gcc_context, GCC_JIT_TYPE_BOOL);
87 }
88 else
89 {
90 oberon_error(ctx, "oberon_generator_init_type: invalid type class %i", type -> class);
91 }
93 type -> gen_type = gen_type;
94 }
96 void
97 oberon_generator_init_var(oberon_context_t * ctx, oberon_object_t * var)
98 {
99 printcontext(ctx, "oberon_generator_init_var");
100 assert(var -> class == OBERON_CLASS_VAR);
102 gen_context_t * gen_context = ctx -> gen_context;
103 gcc_jit_context * gcc_context = gen_context -> gcc_context;
104 gcc_jit_type * gen_type = var -> type -> gen_type;
105 const char * name = var -> name;
107 gcc_jit_lvalue * gen_var;
108 gen_var = gcc_jit_context_new_global(gcc_context, NULL, GCC_JIT_GLOBAL_INTERNAL, gen_type, name);
110 var -> gen_var = gen_var;
113 void
114 oberon_generator_init_proc(oberon_context_t * ctx, oberon_object_t * proc)
116 assert(proc -> class == OBERON_CLASS_PROC);
118 gen_context_t * gen_context = ctx -> gen_context;
119 gcc_jit_context * gcc_context = gen_context -> gcc_context;
120 //gcc_jit_type * gen_type = proc -> type -> gen_type;
121 const char * name = proc -> name;
123 gcc_jit_function * gen_proc;
125 // TODO make real signature
126 gcc_jit_type * void_type = gcc_jit_context_get_type(gcc_context, GCC_JIT_TYPE_VOID);
127 gen_proc = gcc_jit_context_new_function(
128 gcc_context, NULL, GCC_JIT_FUNCTION_EXPORTED, void_type, name, 0, NULL, 0
129 );
131 proc -> gen_proc = gen_proc;
134 // =======================================================================
135 // GENERATOR
136 // =======================================================================
138 static gcc_jit_rvalue * rvalue_from_expr(oberon_context_t * ctx, oberon_expr_t * expr);
140 void
141 oberon_generate_begin_module(oberon_context_t * ctx)
143 printcontext(ctx, "oberon_generate_begin_module");
145 gen_context_t * gen_context = ctx -> gen_context;
146 gcc_jit_context * gcc_context = gen_context -> gcc_context;
148 gcc_jit_type * void_type = gcc_jit_context_get_type(gcc_context, GCC_JIT_TYPE_VOID);
149 gcc_jit_function * func = gcc_jit_context_new_function(
150 gcc_context, NULL, GCC_JIT_FUNCTION_EXPORTED, void_type, "BEGIN", 0, NULL, 0
151 );
152 gcc_jit_block * gcc_block = gcc_jit_function_new_block(func, NULL);
154 gen_context -> gcc_block = gcc_block;
157 void
158 oberon_generate_end_module(oberon_context_t * ctx)
160 printcontext(ctx, "oberon_generate_end_module");
162 gen_context_t * gen_context = ctx -> gen_context;
163 gcc_jit_block * gcc_block = gen_context -> gcc_block;
165 gcc_jit_block_end_with_void_return(gcc_block, NULL);
167 gen_context -> gcc_block = NULL;
170 void
171 oberon_generate_begin_proc(oberon_context_t * ctx, oberon_object_t * proc)
173 gen_context_t * gen_context = ctx -> gen_context;
175 gcc_jit_function * func = proc -> gen_proc;
176 gcc_jit_block * gcc_block = gcc_jit_function_new_block(func, NULL);
178 // TODO make stack for block
179 gen_context -> gcc_block = gcc_block;
182 void
183 oberon_generate_call_proc(oberon_context_t * ctx, oberon_expr_t * desig)
185 gen_context_t * gen_context = ctx -> gen_context;
186 gcc_jit_block * block = gen_context -> gcc_block;
188 gcc_jit_rvalue * return_value;
189 return_value = rvalue_from_expr(ctx, desig);
190 gcc_jit_block_add_eval(block, NULL, return_value);
193 void
194 oberon_generate_end_proc(oberon_context_t * ctx)
196 gen_context_t * gen_context = ctx -> gen_context;
197 gcc_jit_block * gcc_block = gen_context -> gcc_block;
199 gcc_jit_block_end_with_void_return(gcc_block, NULL);
201 gen_context -> gcc_block = NULL;
204 static gcc_jit_lvalue *
205 lvalue_from_expr(oberon_context_t *ctx, oberon_expr_t * expr)
207 gcc_jit_lvalue * left;
208 oberon_item_t * item;
210 if(expr -> is_item)
212 item = (oberon_item_t *) expr;
213 if(item -> mode != MODE_VAR)
215 oberon_error(ctx, "invalid lvalue expression");
217 left = item -> var -> gen_var;
219 else
221 oberon_error(ctx, "invalid lvalue expression");
224 return left;
227 static gcc_jit_rvalue *
228 rvalue_from_item(oberon_context_t * ctx, oberon_item_t * item)
230 gen_context_t * gen_context = ctx -> gen_context;
231 gcc_jit_context * gcc_context = gen_context -> gcc_context;
233 gcc_jit_rvalue * right;
234 if(item -> mode == MODE_VAR)
236 assert(item -> var -> class == OBERON_CLASS_VAR);
237 gcc_jit_lvalue * gen_var = item -> var -> gen_var;
238 right = gcc_jit_lvalue_as_rvalue(gen_var);
240 else if(item -> mode == MODE_INTEGER)
242 gcc_jit_type * int_type = gcc_jit_context_get_type(gcc_context, GCC_JIT_TYPE_INT);
243 right = gcc_jit_context_new_rvalue_from_int(gcc_context, int_type, item -> integer);
245 else if(item -> mode == MODE_BOOLEAN)
247 gcc_jit_type * bool_type = gcc_jit_context_get_type(gcc_context, GCC_JIT_TYPE_BOOL);
248 if(item -> boolean)
250 right = gcc_jit_context_one(gcc_context, bool_type);
252 else
254 right = gcc_jit_context_zero(gcc_context, bool_type);
257 else if(item -> mode == MODE_CALL)
259 assert(item -> var -> class == OBERON_CLASS_PROC);
260 /* TODO args */
261 gcc_jit_function * func = item -> var -> gen_proc;
262 right = gcc_jit_context_new_call(
263 gcc_context, NULL, func, 0, NULL
264 );
266 else
268 oberon_error(ctx, "oberon_generate_push: invalid mode %i", item -> mode);
271 return right;
274 struct {
275 int type; // 0 - unary, 1 - binary, 2 - comp
276 union {
277 enum gcc_jit_unary_op unary_op;
278 enum gcc_jit_binary_op binary_op;
279 enum gcc_jit_comparison comp_op;
280 };
281 } op_table[] = {
282 { 0, .unary_op = GCC_JIT_UNARY_OP_LOGICAL_NEGATE },
283 { 0, .unary_op = GCC_JIT_UNARY_OP_MINUS },
285 { 1, .binary_op = GCC_JIT_BINARY_OP_PLUS },
286 { 1, .binary_op = GCC_JIT_BINARY_OP_MINUS },
287 { 1, .binary_op = GCC_JIT_BINARY_OP_DIVIDE },
288 { 1, .binary_op = GCC_JIT_BINARY_OP_MODULO },
289 { 1, .binary_op = GCC_JIT_BINARY_OP_LOGICAL_AND },
290 { 1, .binary_op = GCC_JIT_BINARY_OP_LOGICAL_OR },
292 { 2, .comp_op = GCC_JIT_COMPARISON_EQ },
293 { 2, .comp_op = GCC_JIT_COMPARISON_NE },
294 { 2, .comp_op = GCC_JIT_COMPARISON_LT },
295 { 2, .comp_op = GCC_JIT_COMPARISON_LE },
296 { 2, .comp_op = GCC_JIT_COMPARISON_GT },
297 { 2, .comp_op = GCC_JIT_COMPARISON_GE }
298 };
300 static gcc_jit_rvalue *
301 rvalue_from_operator(oberon_context_t * ctx, oberon_oper_t * operator)
303 gcc_jit_rvalue * right;
305 gen_context_t * gen_context = ctx -> gen_context;
306 gcc_jit_context * gcc_context = gen_context -> gcc_context;
307 gcc_jit_type * result_type = operator -> result -> gen_type;
309 int expr_type = op_table[operator -> op].type;
310 if(expr_type == 0)
312 enum gcc_jit_unary_op op = op_table[operator -> op].unary_op;
313 gcc_jit_rvalue * l = rvalue_from_expr(ctx, operator -> left);
314 right = gcc_jit_context_new_unary_op(gcc_context, NULL, op, result_type, l);
316 else if(expr_type == 1)
318 enum gcc_jit_unary_op op = op_table[operator -> op].binary_op;
319 gcc_jit_rvalue * l = rvalue_from_expr(ctx, operator -> left);
320 gcc_jit_rvalue * r = rvalue_from_expr(ctx, operator -> right);
321 right = gcc_jit_context_new_binary_op(gcc_context, NULL, op, result_type, l, r);
323 else if(expr_type == 2)
325 enum gcc_jit_comparison op = op_table[operator -> op].comp_op;
326 gcc_jit_rvalue * l = rvalue_from_expr(ctx, operator -> left);
327 gcc_jit_rvalue * r = rvalue_from_expr(ctx, operator -> right);
328 right = gcc_jit_context_new_comparison(gcc_context, NULL, op, l, r);
330 else
332 oberon_error(ctx, "rvalue_from_operator: wat");
335 return right;
338 static gcc_jit_rvalue *
339 rvalue_from_expr(oberon_context_t * ctx, oberon_expr_t * expr)
341 gcc_jit_rvalue * right;
343 if(expr -> is_item)
345 oberon_item_t * item = (oberon_item_t *) expr;
346 right = rvalue_from_item(ctx, item);
348 else
350 oberon_oper_t * operator = (oberon_oper_t *) expr;
351 right = rvalue_from_operator(ctx, operator);
354 return right;
357 void
358 oberon_generate_assign(oberon_context_t * ctx, oberon_expr_t * src, oberon_expr_t * dst)
360 gcc_jit_lvalue * left;
361 left = lvalue_from_expr(ctx, dst);
363 gcc_jit_rvalue * right;
364 right = rvalue_from_expr(ctx, src);
366 gen_context_t * gen_context = ctx -> gen_context;
367 gcc_jit_block * gcc_block = gen_context -> gcc_block;
368 gcc_jit_block_add_assignment(gcc_block, NULL, left, right);
371 void
372 oberon_generate_code(oberon_context_t * ctx)
374 gen_context_t * gen_context = ctx -> gen_context;
375 gcc_jit_context * gcc_context = gen_context -> gcc_context;
377 gcc_jit_result * gcc_result;
378 gcc_result = gcc_jit_context_compile(gcc_context);
380 gen_context -> gcc_result = gcc_result;
381 ctx -> mod -> begin = gcc_jit_result_get_code(gcc_result, "BEGIN");