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
= NULL
;
69 gcc_jit_struct
* gcc_struct
= NULL
;
70 if(type
-> class == OBERON_TYPE_VOID
)
72 gcc_type
= gcc_jit_context_get_type(gcc_context
, GCC_JIT_TYPE_VOID
);
74 else if(type
-> class == OBERON_TYPE_INTEGER
)
76 gcc_type
= gcc_jit_context_get_int_type(gcc_context
, type
-> size
, 1);
78 else if(type
-> class == OBERON_TYPE_BOOLEAN
)
80 gcc_type
= gcc_jit_context_get_type(gcc_context
, GCC_JIT_TYPE_BOOL
);
82 else if(type
-> class == OBERON_TYPE_ARRAY
)
84 gen_type_t
* gen_base
= type
-> base
-> gen_type
;
85 gcc_jit_type
* gcc_base
= gen_base
-> gcc_type
;
86 gcc_type
= gcc_jit_context_new_array_type(gcc_context
, NULL
, gcc_base
, type
-> size
);
88 else if(type
-> class == OBERON_TYPE_RECORD
)
90 gcc_struct
= gcc_jit_context_new_opaque_struct(gcc_context
, NULL
, "");
91 gcc_type
= gcc_jit_struct_as_type(gcc_struct
);
93 else if(type
-> class == OBERON_TYPE_POINTER
)
95 gen_type_t
* gen_base
= type
-> base
-> gen_type
;
96 gcc_jit_type
* gcc_base
= gen_base
-> gcc_type
;
97 gcc_type
= gcc_jit_type_get_pointer(gcc_base
);
99 else if(type
-> class == OBERON_TYPE_PROCEDURE
)
101 int num_params
= type
-> num_decl
;
102 gcc_jit_type
* params
[num_params
];
103 oberon_object_t
* o
= type
-> decl
;
104 for(int i
= 0; i
< num_params
; i
++)
106 gen_type_t
* gen_type
= o
-> type
-> gen_type
;
107 params
[i
] = gen_type
-> gcc_type
;
111 gen_type_t
* base
= type
-> base
-> gen_type
;
112 gcc_jit_type
* result_type
= base
-> gcc_type
;
114 gcc_type
= gcc_jit_context_new_function_ptr_type(
115 gcc_context
, NULL
, result_type
, num_params
, params
, 0
120 oberon_error(ctx
, "oberon_generator_init_type: invalid type class %i", type
-> class);
124 gen_type
-> gcc_type
= gcc_type
;
125 gen_type
-> gcc_struct
= gcc_struct
;
129 oberon_generator_init_record(oberon_context_t
* ctx
, oberon_type_t
* type
)
131 assert(type
-> class == OBERON_TYPE_RECORD
);
133 gen_type_t
* gen_type
= type
-> gen_type
;
134 gcc_jit_struct
* gcc_struct
= gen_type
-> gcc_struct
;
136 // TODO type exstension
138 int num_fields
= type
-> num_decl
;
139 gcc_jit_field
* fields
[num_fields
];
140 oberon_object_t
* o
= type
-> decl
;
141 for(int i
= 0; i
< num_fields
; i
++)
143 assert(o
-> class == OBERON_CLASS_FIELD
);
144 gen_var_t
* var
= o
-> gen_var
;
145 fields
[i
] = var
-> gcc_field
;
149 gcc_jit_struct_set_fields (gcc_struct
, NULL
, num_fields
, fields
);
151 //gcc_struct = gcc_jit_context_new_struct_type(gcc_context, NULL, "", num_fields, fields);
155 oberon_generator_init_var(oberon_context_t
* ctx
, oberon_object_t
* var
)
157 gen_context_t
* gen_context
= ctx
-> gen_context
;
158 gen_type_t
* gen_type
= var
-> type
-> gen_type
;
160 gen_var_t
* gen_var
= malloc(sizeof *gen_var
);
161 memset(gen_var
, 0, sizeof *gen_var
);
162 var
-> gen_var
= gen_var
;
164 gcc_jit_context
* gcc_context
= gen_context
-> gcc_context
;
165 gcc_jit_type
* gcc_type
= gen_type
-> gcc_type
;
166 const char * name
= var
-> name
;
168 gcc_jit_lvalue
* gcc_lvalue
= NULL
;
169 gcc_jit_param
* gcc_param
= NULL
;
170 gcc_jit_field
* gcc_field
= NULL
;
171 if(var
-> class == OBERON_CLASS_VAR
)
173 gcc_lvalue
= gcc_jit_context_new_global(
174 gcc_context
, NULL
, GCC_JIT_GLOBAL_INTERNAL
, gcc_type
, name
177 else if(var
-> class == OBERON_CLASS_PARAM
)
179 gcc_param
= gcc_jit_context_new_param(gcc_context
, NULL
, gcc_type
, name
);
180 gcc_lvalue
= gcc_jit_param_as_lvalue(gcc_param
);
182 else if(var
-> class == OBERON_CLASS_VAR_PARAM
)
184 gcc_type
= gcc_jit_type_get_pointer(gcc_type
);
185 gcc_param
= gcc_jit_context_new_param(gcc_context
, NULL
, gcc_type
, name
);
186 gcc_lvalue
= gcc_jit_param_as_lvalue(gcc_param
);
188 else if(var
-> class == OBERON_CLASS_FIELD
)
190 gcc_field
= gcc_jit_context_new_field(gcc_context
, NULL
, gcc_type
, name
);
194 oberon_error(ctx
, "oberon_generator_init_var: invalid class %i", var
-> class);
197 gen_var
-> gcc_lvalue
= gcc_lvalue
;
198 gen_var
-> gcc_param
= gcc_param
;
199 gen_var
-> gcc_field
= gcc_field
;
203 oberon_generator_init_proc(oberon_context_t
* ctx
, oberon_object_t
* proc
)
205 assert(proc
-> class == OBERON_CLASS_PROC
);
207 gen_context_t
* gen_context
= ctx
-> gen_context
;
208 gcc_jit_context
* gcc_context
= gen_context
-> gcc_context
;
210 gen_proc_t
* gen_proc
= malloc(sizeof *gen_proc
);
211 memset(gen_proc
, 0, sizeof *gen_proc
);
212 proc
-> gen_proc
= gen_proc
;
214 const char * name
= proc
-> name
;
215 gen_type_t
* gen_result_type
= proc
-> type
-> base
-> gen_type
;
216 gcc_jit_type
* result_type
= gen_result_type
-> gcc_type
;
218 /* Строим список параметров */
219 int num_param
= proc
-> type
-> num_decl
;
220 oberon_object_t
* o
= proc
-> type
-> decl
;
221 gcc_jit_param
* params
[num_param
];
222 for(int i
= 0; i
< num_param
; i
++)
224 gen_var_t
* param_var
= o
-> gen_var
;
225 params
[i
] = param_var
-> gcc_param
;
229 gcc_jit_function
* gcc_func
;
230 gcc_func
= gcc_jit_context_new_function(
231 gcc_context
, NULL
, GCC_JIT_FUNCTION_EXPORTED
, result_type
, name
, num_param
, params
, 0
234 gen_proc
-> gcc_func
= gcc_func
;
237 // =======================================================================
239 // =======================================================================
241 static gcc_jit_rvalue
* rvalue_from_item(oberon_context_t
* ctx
, oberon_item_t
* item
);
242 static gcc_jit_rvalue
* rvalue_from_expr(oberon_context_t
* ctx
, oberon_expr_t
* expr
);
245 oberon_generate_begin_module(oberon_context_t
* ctx
)
247 printcontext(ctx
, "oberon_generate_begin_module");
249 gen_context_t
* gen_context
= ctx
-> gen_context
;
250 gcc_jit_context
* gcc_context
= gen_context
-> gcc_context
;
252 gcc_jit_type
* void_type
= gcc_jit_context_get_type(gcc_context
, GCC_JIT_TYPE_VOID
);
253 gcc_jit_function
* func
= gcc_jit_context_new_function(
254 gcc_context
, NULL
, GCC_JIT_FUNCTION_EXPORTED
, void_type
, "BEGIN", 0, NULL
, 0
256 gcc_jit_block
* gcc_block
= gcc_jit_function_new_block(func
, NULL
);
258 gen_context
-> gcc_block
= gcc_block
;
262 oberon_generate_end_module(oberon_context_t
* ctx
)
264 printcontext(ctx
, "oberon_generate_end_module");
266 gen_context_t
* gen_context
= ctx
-> gen_context
;
267 gcc_jit_block
* gcc_block
= gen_context
-> gcc_block
;
269 gcc_jit_block_end_with_void_return(gcc_block
, NULL
);
271 gen_context
-> gcc_block
= NULL
;
275 oberon_generate_begin_proc(oberon_context_t
* ctx
, oberon_object_t
* proc
)
277 gen_context_t
* gen_context
= ctx
-> gen_context
;
278 gen_proc_t
* gen_proc
= proc
-> gen_proc
;
280 gcc_jit_function
* func
= gen_proc
-> gcc_func
;
281 gcc_jit_block
* gcc_block
= gcc_jit_function_new_block(func
, NULL
);
283 // TODO make stack for block
284 gen_context
-> gcc_block
= gcc_block
;
288 oberon_generate_call_proc(oberon_context_t
* ctx
, oberon_expr_t
* desig
)
290 gen_context_t
* gen_context
= ctx
-> gen_context
;
291 gcc_jit_block
* block
= gen_context
-> gcc_block
;
293 gcc_jit_rvalue
* return_value
;
294 return_value
= rvalue_from_expr(ctx
, desig
);
295 gcc_jit_block_add_eval(block
, NULL
, return_value
);
299 oberon_generate_end_proc(oberon_context_t
* ctx
)
301 gen_context_t
* gen_context
= ctx
-> gen_context
;
302 gen_context
-> gcc_block
= NULL
;
306 oberon_generate_return(oberon_context_t
* ctx
, oberon_expr_t
* expr
)
308 gen_context_t
* gen_context
= ctx
-> gen_context
;
309 gcc_jit_block
* gcc_block
= gen_context
-> gcc_block
;
313 gcc_jit_block_end_with_void_return(gcc_block
, NULL
);
317 gcc_jit_rvalue
* r
= rvalue_from_expr(ctx
, expr
);
318 gcc_jit_block_end_with_return(gcc_block
, NULL
, r
);
322 static gcc_jit_lvalue
*
323 lvalue_from_item(oberon_context_t
* ctx
, oberon_item_t
* item
)
325 gen_context_t
* gen_context
= ctx
-> gen_context
;
326 gcc_jit_context
* gcc_context
= gen_context
-> gcc_context
;
328 gcc_jit_lvalue
* left
;
330 if(item
-> mode
== MODE_VAR
)
332 gen_var_t
* gen_var
= item
-> var
-> gen_var
;
333 left
= gen_var
-> gcc_lvalue
;
334 if(item
-> var
-> class == OBERON_CLASS_VAR_PARAM
)
336 gcc_jit_rvalue
* r
= gcc_jit_lvalue_as_rvalue(left
);
337 left
= gcc_jit_rvalue_dereference(r
, NULL
);
340 else if(item
-> mode
== MODE_INDEX
)
342 assert(item
-> num_args
== 1);
343 gcc_jit_rvalue
* parent
= rvalue_from_item(ctx
, item
-> parent
);
344 gcc_jit_rvalue
* index
= rvalue_from_expr(ctx
, item
-> args
);
345 left
= gcc_jit_context_new_array_access(gcc_context
, NULL
, parent
, index
);
347 else if(item
-> mode
== MODE_FIELD
)
349 printf("lvalue_from_item: %s\n", item
-> var
-> name
);
350 gen_var_t
* gen_var
= item
-> var
-> gen_var
;
351 gcc_jit_field
* gcc_field
= gen_var
-> gcc_field
;
353 gcc_jit_lvalue
* parent
= lvalue_from_item(ctx
, item
-> parent
);
354 left
= gcc_jit_lvalue_access_field(parent
, NULL
, gcc_field
);
356 else if(item
-> mode
== MODE_DEREF
)
358 gcc_jit_rvalue
* parent
= rvalue_from_item(ctx
, item
-> parent
);
359 left
= gcc_jit_rvalue_dereference(parent
, NULL
);
363 oberon_error(ctx
, "invalid lvalue expression");
369 static gcc_jit_lvalue
*
370 lvalue_from_expr(oberon_context_t
*ctx
, oberon_expr_t
* expr
)
372 gcc_jit_lvalue
* left
;
373 oberon_item_t
* item
;
377 item
= (oberon_item_t
*) expr
;
378 left
= lvalue_from_item(ctx
, item
);
382 oberon_error(ctx
, "invalid lvalue expression");
388 static gcc_jit_rvalue
*
389 rvalue_from_item(oberon_context_t
* ctx
, oberon_item_t
* item
)
391 gen_context_t
* gen_context
= ctx
-> gen_context
;
392 gcc_jit_context
* gcc_context
= gen_context
-> gcc_context
;
394 gcc_jit_rvalue
* right
;
395 if(item
-> mode
== MODE_VAR
)
397 gcc_jit_lvalue
* left
= lvalue_from_item(ctx
, item
);
398 right
= gcc_jit_lvalue_as_rvalue(left
);
400 else if(item
-> mode
== MODE_INTEGER
)
402 gcc_jit_type
* int_type
= gcc_jit_context_get_type(gcc_context
, GCC_JIT_TYPE_INT
);
403 right
= gcc_jit_context_new_rvalue_from_int(gcc_context
, int_type
, item
-> integer
);
405 else if(item
-> mode
== MODE_BOOLEAN
)
407 gcc_jit_type
* bool_type
= gcc_jit_context_get_type(gcc_context
, GCC_JIT_TYPE_BOOL
);
410 right
= gcc_jit_context_one(gcc_context
, bool_type
);
414 right
= gcc_jit_context_zero(gcc_context
, bool_type
);
417 else if(item
-> mode
== MODE_CALL
)
419 assert(item
-> var
-> class == OBERON_CLASS_PROC
);
421 oberon_type_t
* signature
= item
-> var
-> type
;
422 gen_proc_t
* gen_proc
= item
-> var
-> gen_proc
;
424 int num_args
= item
-> num_args
;
425 gcc_jit_rvalue
*args
[num_args
];
427 oberon_expr_t
* expr
= item
-> args
;
428 oberon_object_t
* arg_param
= signature
-> decl
;
429 for(int i
= 0; i
< num_args
; i
++)
431 if(arg_param
-> class == OBERON_CLASS_VAR_PARAM
)
433 gcc_jit_lvalue
* left
= lvalue_from_expr(ctx
, expr
);
434 args
[i
] = gcc_jit_lvalue_get_address(left
, NULL
);
438 args
[i
] = rvalue_from_expr(ctx
, expr
);
441 arg_param
= arg_param
-> next
;
444 gcc_jit_function
* func
= gen_proc
-> gcc_func
;
445 right
= gcc_jit_context_new_call(
446 gcc_context
, NULL
, func
, num_args
, args
449 else if(item
-> mode
== MODE_INDEX
)
451 gcc_jit_lvalue
* left
= lvalue_from_item(ctx
, item
);
452 right
= gcc_jit_lvalue_as_rvalue(left
);
454 else if(item
-> mode
== MODE_FIELD
)
456 gen_var_t
* gen_var
= item
-> var
-> gen_var
;
457 gcc_jit_field
* gcc_field
= gen_var
-> gcc_field
;
459 gcc_jit_rvalue
* parent
= rvalue_from_item(ctx
, item
-> parent
);
460 right
= gcc_jit_rvalue_access_field(parent
, NULL
, gcc_field
);
462 else if(item
-> mode
== MODE_DEREF
)
464 gcc_jit_lvalue
* left
= lvalue_from_item(ctx
, item
);
465 right
= gcc_jit_lvalue_as_rvalue(left
);
467 else if(item
-> mode
== MODE_NIL
)
469 gcc_jit_type
* type
= gcc_jit_context_get_type(gcc_context
, GCC_JIT_TYPE_VOID_PTR
);
470 right
= gcc_jit_context_null(gcc_context
, type
);
474 oberon_error(ctx
, "rvalue_from_item: invalid mode %i", item
-> mode
);
481 int type
; // 0 - unary, 1 - binary, 2 - comp
483 enum gcc_jit_unary_op unary_op
;
484 enum gcc_jit_binary_op binary_op
;
485 enum gcc_jit_comparison comp_op
;
488 { 0, .unary_op
= GCC_JIT_UNARY_OP_LOGICAL_NEGATE
},
489 { 0, .unary_op
= GCC_JIT_UNARY_OP_MINUS
},
491 { 1, .binary_op
= GCC_JIT_BINARY_OP_PLUS
},
492 { 1, .binary_op
= GCC_JIT_BINARY_OP_MINUS
},
493 { 1, .binary_op
= GCC_JIT_BINARY_OP_MULT
},
494 { 1, .binary_op
= GCC_JIT_BINARY_OP_DIVIDE
},
495 { 1, .binary_op
= GCC_JIT_BINARY_OP_MODULO
},
496 { 1, .binary_op
= GCC_JIT_BINARY_OP_LOGICAL_AND
},
497 { 1, .binary_op
= GCC_JIT_BINARY_OP_LOGICAL_OR
},
499 { 2, .comp_op
= GCC_JIT_COMPARISON_EQ
},
500 { 2, .comp_op
= GCC_JIT_COMPARISON_NE
},
501 { 2, .comp_op
= GCC_JIT_COMPARISON_LT
},
502 { 2, .comp_op
= GCC_JIT_COMPARISON_LE
},
503 { 2, .comp_op
= GCC_JIT_COMPARISON_GT
},
504 { 2, .comp_op
= GCC_JIT_COMPARISON_GE
}
507 static gcc_jit_rvalue
*
508 rvalue_from_operator(oberon_context_t
* ctx
, oberon_oper_t
* operator)
510 gcc_jit_rvalue
* right
;
512 gen_context_t
* gen_context
= ctx
-> gen_context
;
513 gen_type_t
* gen_type
= operator -> result
-> gen_type
;
514 gcc_jit_context
* gcc_context
= gen_context
-> gcc_context
;
515 gcc_jit_type
* result_type
= gen_type
-> gcc_type
;
517 int expr_type
= op_table
[operator -> op
].type
;
520 enum gcc_jit_unary_op op
= op_table
[operator -> op
].unary_op
;
521 gcc_jit_rvalue
* l
= rvalue_from_expr(ctx
, operator -> left
);
522 right
= gcc_jit_context_new_unary_op(gcc_context
, NULL
, op
, result_type
, l
);
524 else if(expr_type
== 1)
526 enum gcc_jit_unary_op op
= op_table
[operator -> op
].binary_op
;
527 gcc_jit_rvalue
* l
= rvalue_from_expr(ctx
, operator -> left
);
528 gcc_jit_rvalue
* r
= rvalue_from_expr(ctx
, operator -> right
);
529 right
= gcc_jit_context_new_binary_op(gcc_context
, NULL
, op
, result_type
, l
, r
);
531 else if(expr_type
== 2)
533 enum gcc_jit_comparison op
= op_table
[operator -> op
].comp_op
;
534 gcc_jit_rvalue
* l
= rvalue_from_expr(ctx
, operator -> left
);
535 gcc_jit_rvalue
* r
= rvalue_from_expr(ctx
, operator -> right
);
536 right
= gcc_jit_context_new_comparison(gcc_context
, NULL
, op
, l
, r
);
540 oberon_error(ctx
, "rvalue_from_operator: wat");
546 static gcc_jit_rvalue
*
547 rvalue_from_expr(oberon_context_t
* ctx
, oberon_expr_t
* expr
)
549 gcc_jit_rvalue
* right
;
553 oberon_item_t
* item
= (oberon_item_t
*) expr
;
554 right
= rvalue_from_item(ctx
, item
);
558 oberon_oper_t
* operator = (oberon_oper_t
*) expr
;
559 right
= rvalue_from_operator(ctx
, operator);
566 oberon_generate_assign(oberon_context_t
* ctx
, oberon_expr_t
* src
, oberon_expr_t
* dst
)
568 gcc_jit_lvalue
* left
;
569 left
= lvalue_from_expr(ctx
, dst
);
571 gcc_jit_rvalue
* right
;
572 right
= rvalue_from_expr(ctx
, src
);
576 if(src
-> item
.mode
== MODE_NIL
)
578 gen_context_t
* gen_context
= ctx
-> gen_context
;
579 gcc_jit_context
* gcc_context
= gen_context
-> gcc_context
;
580 gen_type_t
* gen_type
= dst
-> result
-> gen_type
;
581 gcc_jit_type
* cast_to_type
= gen_type
-> gcc_type
;
582 right
= gcc_jit_context_new_cast(gcc_context
, NULL
, right
, cast_to_type
);
586 gen_context_t
* gen_context
= ctx
-> gen_context
;
587 gcc_jit_block
* gcc_block
= gen_context
-> gcc_block
;
588 gcc_jit_block_add_assignment(gcc_block
, NULL
, left
, right
);
592 oberon_generate_code(oberon_context_t
* ctx
)
594 gen_context_t
* gen_context
= ctx
-> gen_context
;
595 gcc_jit_context
* gcc_context
= gen_context
-> gcc_context
;
597 gcc_jit_result
* gcc_result
;
598 gcc_result
= gcc_jit_context_compile(gcc_context
);
600 gen_context
-> gcc_result
= gcc_result
;
601 ctx
-> mod
-> begin
= gcc_jit_result_get_code(gcc_result
, "BEGIN");
605 oberon_generator_dump(oberon_context_t
* ctx
, char * path
)
607 gen_context_t
* gen_context
= ctx
-> gen_context
;
608 gcc_jit_context
* gcc_context
= gen_context
-> gcc_context
;
609 gcc_jit_context_dump_to_file(gcc_context
, path
, 0);