11 #include <libgccjit.h>
13 static void printcontext(oberon_context_t
* ctx
, char * s
)
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;
21 printf(" ctx = %p:\n", ctx);
22 printf(" gctx = %p:\n", gctx);
23 printf(" context = %p:\n", context);
24 printf(" block = %p:\n", block);
28 // =======================================================================
30 // =======================================================================
33 oberon_generator_init_context(oberon_context_t
* ctx
)
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");
48 oberon_generator_destroy_context(oberon_context_t
* ctx
)
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
);
59 oberon_generator_init_type(oberon_context_t
* ctx
, oberon_type_t
* type
)
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
)
71 gcc_type
= gcc_jit_context_get_type(gcc_context
, GCC_JIT_TYPE_VOID
);
73 else if(type
-> class == OBERON_TYPE_INTEGER
)
75 gcc_type
= gcc_jit_context_get_int_type(gcc_context
, type
-> size
, 1);
77 else if(type
-> class == OBERON_TYPE_BOOLEAN
)
79 gcc_type
= gcc_jit_context_get_type(gcc_context
, GCC_JIT_TYPE_BOOL
);
81 else if(type
-> class == OBERON_TYPE_PROCEDURE
)
83 gcc_type
= NULL
; // not used
85 else if(type
-> class == OBERON_TYPE_ARRAY
)
89 oberon_error(ctx
, "multidimension and open arrays not supported");
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
);
99 oberon_error(ctx
, "oberon_generator_init_type: invalid type class %i", type
-> class);
102 gen_type
-> gcc_type
= gcc_type
;
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
;
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
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
);
133 oberon_error(ctx
, "oberon_generator_init_var: invalid class %i", var
-> class);
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
;
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
169 gen_proc
-> gcc_func
= gcc_func
;
172 // =======================================================================
174 // =======================================================================
176 static gcc_jit_rvalue
* rvalue_from_expr(oberon_context_t
* ctx
, oberon_expr_t
* expr
);
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
190 gcc_jit_block
* gcc_block
= gcc_jit_function_new_block(func
, NULL
);
192 gen_context
-> gcc_block
= gcc_block
;
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
;
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
;
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
);
233 oberon_generate_end_proc(oberon_context_t
* ctx
)
235 gen_context_t
* gen_context
= ctx
-> gen_context
;
236 gen_context
-> gcc_block
= NULL
;
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
;
247 gcc_jit_block_end_with_void_return(gcc_block
, NULL
);
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
;
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
;
274 oberon_error(ctx
, "invalid lvalue expression");
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
);
304 right
= gcc_jit_context_one(gcc_context
, bool_type
);
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
);
327 gcc_jit_function
* func
= gen_proc
-> gcc_func
;
328 right
= gcc_jit_context_new_call(
329 gcc_context
, NULL
, func
, num_args
, args
334 oberon_error(ctx
, "oberon_generate_push: invalid mode %i", item
-> mode
);
341 int type
; // 0 - unary, 1 - binary, 2 - comp
343 enum gcc_jit_unary_op unary_op
;
344 enum gcc_jit_binary_op binary_op
;
345 enum gcc_jit_comparison comp_op
;
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
}
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
;
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
);
399 oberon_error(ctx
, "rvalue_from_operator: wat");
405 static gcc_jit_rvalue
*
406 rvalue_from_expr(oberon_context_t
* ctx
, oberon_expr_t
* expr
)
408 gcc_jit_rvalue
* right
;
412 oberon_item_t
* item
= (oberon_item_t
*) expr
;
413 right
= rvalue_from_item(ctx
, item
);
417 oberon_oper_t
* operator = (oberon_oper_t
*) expr
;
418 right
= rvalue_from_operator(ctx
, operator);
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
);
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");