DEADSOFTWARE

Добавлены процедуры и проверка результата в выражениях
[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_var_t -> gvar == gcc_jit_lvalue;
15 * oberon_type_t -> gtype == gcc_jit_type;
16 * oberon_context_t -> gctx == 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_var_t * var)
98 {
99 printcontext(ctx, "oberon_generator_init_var");
101 gen_context_t * gen_context = ctx -> gen_context;
102 gcc_jit_context * gcc_context = gen_context -> gcc_context;
103 gcc_jit_type * gen_type = var -> type -> gen_type;
104 const char * name = var -> name;
106 gcc_jit_lvalue * gen_var;
107 gen_var = gcc_jit_context_new_global(gcc_context, NULL, GCC_JIT_GLOBAL_INTERNAL, gen_type, name);
109 var -> gen_var = gen_var;
112 // =======================================================================
113 // GENERATOR
114 // =======================================================================
116 void
117 oberon_generate_begin_module(oberon_context_t * ctx)
119 printcontext(ctx, "oberon_generate_begin_module");
121 gen_context_t * gen_context = ctx -> gen_context;
122 gcc_jit_context * gcc_context = gen_context -> gcc_context;
124 gcc_jit_type * void_type = gcc_jit_context_get_type(gcc_context, GCC_JIT_TYPE_VOID);
125 gcc_jit_function * func = gcc_jit_context_new_function(
126 gcc_context, NULL, GCC_JIT_FUNCTION_EXPORTED, void_type, "BEGIN", 0, NULL, 0
127 );
128 gcc_jit_block * gcc_block = gcc_jit_function_new_block(func, NULL);
130 gen_context -> gcc_block = gcc_block;
133 void
134 oberon_generate_end_module(oberon_context_t * ctx)
136 printcontext(ctx, "oberon_generate_end_module");
138 gen_context_t * gen_context = ctx -> gen_context;
139 gcc_jit_block * gcc_block = gen_context -> gcc_block;
141 gcc_jit_block_end_with_void_return(gcc_block, NULL);
143 gen_context -> gcc_block = NULL;
146 static gcc_jit_lvalue *
147 lvalue_from_expr(oberon_context_t *ctx, oberon_expr_t * expr)
149 gcc_jit_lvalue * left;
150 oberon_item_t * item;
152 if(expr -> is_item)
154 item = (oberon_item_t *) expr;
155 if(item -> mode != MODE_VAR)
157 oberon_error(ctx, "invalid lvalue expression");
159 left = item -> var -> gen_var;
161 else
163 oberon_error(ctx, "invalid lvalue expression");
166 return left;
169 static gcc_jit_rvalue * rvalue_from_expr(oberon_context_t * ctx, oberon_expr_t * expr);
171 static gcc_jit_rvalue *
172 rvalue_from_item(oberon_context_t * ctx, oberon_item_t * item)
174 gen_context_t * gen_context = ctx -> gen_context;
175 gcc_jit_context * gcc_context = gen_context -> gcc_context;
177 gcc_jit_rvalue * right;
178 if(item -> mode == MODE_VAR)
180 gcc_jit_lvalue * gen_var = item -> var -> gen_var;
181 right = gcc_jit_lvalue_as_rvalue(gen_var);
183 else if(item -> mode == MODE_INTEGER)
185 gcc_jit_type * int_type = gcc_jit_context_get_type(gcc_context, GCC_JIT_TYPE_INT);
186 right = gcc_jit_context_new_rvalue_from_int(gcc_context, int_type, item -> integer);
188 else if(item -> mode == MODE_BOOLEAN)
190 gcc_jit_type * bool_type = gcc_jit_context_get_type(gcc_context, GCC_JIT_TYPE_BOOL);
191 if(item -> boolean)
193 right = gcc_jit_context_one(gcc_context, bool_type);
195 else
197 right = gcc_jit_context_zero(gcc_context, bool_type);
200 else
202 oberon_error(ctx, "oberon_generate_push: invalid mode %i", item -> mode);
205 return right;
208 struct {
209 int type; // 0 - unary, 1 - binary, 2 - comp
210 union {
211 enum gcc_jit_unary_op unary_op;
212 enum gcc_jit_binary_op binary_op;
213 enum gcc_jit_comparison comp_op;
214 };
215 } op_table[] = {
216 { 0, .unary_op = GCC_JIT_UNARY_OP_LOGICAL_NEGATE },
217 { 0, .unary_op = GCC_JIT_UNARY_OP_MINUS },
219 { 1, .binary_op = GCC_JIT_BINARY_OP_PLUS },
220 { 1, .binary_op = GCC_JIT_BINARY_OP_MINUS },
221 { 1, .binary_op = GCC_JIT_BINARY_OP_DIVIDE },
222 { 1, .binary_op = GCC_JIT_BINARY_OP_MODULO },
223 { 1, .binary_op = GCC_JIT_BINARY_OP_LOGICAL_AND },
224 { 1, .binary_op = GCC_JIT_BINARY_OP_LOGICAL_OR },
226 { 2, .comp_op = GCC_JIT_COMPARISON_EQ },
227 { 2, .comp_op = GCC_JIT_COMPARISON_NE },
228 { 2, .comp_op = GCC_JIT_COMPARISON_LT },
229 { 2, .comp_op = GCC_JIT_COMPARISON_LE },
230 { 2, .comp_op = GCC_JIT_COMPARISON_GT },
231 { 2, .comp_op = GCC_JIT_COMPARISON_GE }
232 };
234 static gcc_jit_rvalue *
235 rvalue_from_operator(oberon_context_t * ctx, oberon_oper_t * operator)
237 gcc_jit_rvalue * right;
239 gen_context_t * gen_context = ctx -> gen_context;
240 gcc_jit_context * gcc_context = gen_context -> gcc_context;
241 gcc_jit_type * result_type = operator -> result -> gen_type;
243 int expr_type = op_table[operator -> op].type;
244 if(expr_type == 0)
246 enum gcc_jit_unary_op op = op_table[operator -> op].unary_op;
247 gcc_jit_rvalue * l = rvalue_from_expr(ctx, operator -> left);
248 right = gcc_jit_context_new_unary_op(gcc_context, NULL, op, result_type, l);
250 else if(expr_type == 1)
252 enum gcc_jit_unary_op op = op_table[operator -> op].binary_op;
253 gcc_jit_rvalue * l = rvalue_from_expr(ctx, operator -> left);
254 gcc_jit_rvalue * r = rvalue_from_expr(ctx, operator -> right);
255 right = gcc_jit_context_new_binary_op(gcc_context, NULL, op, result_type, l, r);
257 else if(expr_type == 2)
259 enum gcc_jit_comparison op = op_table[operator -> op].comp_op;
260 gcc_jit_rvalue * l = rvalue_from_expr(ctx, operator -> left);
261 gcc_jit_rvalue * r = rvalue_from_expr(ctx, operator -> right);
262 right = gcc_jit_context_new_comparison(gcc_context, NULL, op, l, r);
264 else
266 oberon_error(ctx, "rvalue_from_operator: wat");
269 return right;
272 static gcc_jit_rvalue *
273 rvalue_from_expr(oberon_context_t * ctx, oberon_expr_t * expr)
275 gcc_jit_rvalue * right;
277 if(expr -> is_item)
279 oberon_item_t * item = (oberon_item_t *) expr;
280 right = rvalue_from_item(ctx, item);
282 else
284 oberon_oper_t * operator = (oberon_oper_t *) expr;
285 right = rvalue_from_operator(ctx, operator);
288 return right;
291 void
292 oberon_generate_assign(oberon_context_t * ctx, oberon_expr_t * src, oberon_expr_t * dst)
294 gcc_jit_lvalue * left;
295 left = lvalue_from_expr(ctx, dst);
297 gcc_jit_rvalue * right;
298 right = rvalue_from_expr(ctx, src);
300 gen_context_t * gen_context = ctx -> gen_context;
301 gcc_jit_block * gcc_block = gen_context -> gcc_block;
302 gcc_jit_block_add_assignment(gcc_block, NULL, left, right);
305 void
306 oberon_generate_code(oberon_context_t * ctx)
308 gen_context_t * gen_context = ctx -> gen_context;
309 gcc_jit_context * gcc_context = gen_context -> gcc_context;
311 gcc_jit_result * gcc_result;
312 gcc_result = gcc_jit_context_compile(gcc_context);
314 gen_context -> gcc_result = gcc_result;
315 ctx -> mod -> begin = gcc_jit_result_get_code(gcc_result, "BEGIN");