DEADSOFTWARE

Добавлены типы INTEGER и BOOLEAN
[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 static gcc_jit_rvalue *
117 oberon_generate_rvalue_from_item(oberon_context_t * ctx, oberon_item_t * item)
119 printcontext(ctx, "oberon_generate_rvalue_from_item");
121 gen_context_t * gen_context = ctx -> gen_context;
122 gcc_jit_context * gcc_context = gen_context -> gcc_context;
124 gcc_jit_rvalue * right;
125 if(item -> mode == MODE_VAR)
127 gcc_jit_lvalue * gen_var = item -> var -> gen_var;
128 right = gcc_jit_lvalue_as_rvalue(gen_var);
129 printf("PUSH (var) %s\n", item -> var -> name);
131 else if(item -> mode == MODE_INTEGER)
133 gcc_jit_type * int_type = gcc_jit_context_get_type(gcc_context, GCC_JIT_TYPE_INT);
134 right = gcc_jit_context_new_rvalue_from_int(gcc_context, int_type, item -> integer);
135 printf("PUSH (int) %i\n", item -> integer);
137 else if(item -> mode == MODE_BOOLEAN)
139 gcc_jit_type * bool_type = gcc_jit_context_get_type(gcc_context, GCC_JIT_TYPE_BOOL);
140 if(item -> boolean)
142 right = gcc_jit_context_one(gcc_context, bool_type);
144 else
146 right = gcc_jit_context_zero(gcc_context, bool_type);
148 printf("PUSH (bool) %i\n", item -> boolean);
150 else
152 oberon_error(ctx, "oberon_generate_push: invalid mode %i", item -> mode);
155 return right;
158 void
159 oberon_generate_begin_module(oberon_context_t * ctx)
161 printcontext(ctx, "oberon_generate_begin_module");
163 gen_context_t * gen_context = ctx -> gen_context;
164 gcc_jit_context * gcc_context = gen_context -> gcc_context;
166 gcc_jit_type * void_type = gcc_jit_context_get_type(gcc_context, GCC_JIT_TYPE_VOID);
167 gcc_jit_function * func = gcc_jit_context_new_function(
168 gcc_context, NULL, GCC_JIT_FUNCTION_EXPORTED, void_type, "BEGIN", 0, NULL, 0
169 );
170 gcc_jit_block * gcc_block = gcc_jit_function_new_block(func, NULL);
172 gen_context -> gcc_block = gcc_block;
175 void
176 oberon_generate_end_module(oberon_context_t * ctx)
178 printcontext(ctx, "oberon_generate_end_module");
180 gen_context_t * gen_context = ctx -> gen_context;
181 gcc_jit_block * gcc_block = gen_context -> gcc_block;
183 gcc_jit_block_end_with_void_return(gcc_block, NULL);
185 gen_context -> gcc_block = NULL;
188 void
189 oberon_generate_assign(oberon_context_t * ctx, oberon_item_t * src, oberon_item_t * dst)
191 printcontext(ctx, "oberon_generate_assign");
193 gen_context_t * gen_context = ctx -> gen_context;
194 gcc_jit_block * gcc_block = gen_context -> gcc_block;
196 gcc_jit_lvalue * left;
197 gcc_jit_rvalue * right;
199 right = oberon_generate_rvalue_from_item(ctx, src);
201 if(dst -> mode == MODE_VAR)
203 printf("STORE %s\n", dst -> var -> name);
204 left = dst -> var -> gen_var;
206 else
208 oberon_error(ctx, "oberon_generate_assign: invalid assignment");
209 }
211 gcc_jit_block_add_assignment(gcc_block, NULL, left, right);
214 void
215 oberon_generate_code(oberon_context_t * ctx)
217 gen_context_t * gen_context = ctx -> gen_context;
218 gcc_jit_context * gcc_context = gen_context -> gcc_context;
220 gcc_jit_result * gcc_result;
221 gcc_result = gcc_jit_context_compile(gcc_context);
223 gen_context -> gcc_result = gcc_result;
224 ctx -> mod -> begin = gcc_jit_result_get_code(gcc_result, "BEGIN");