11 #include <libgccjit.h>
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;
21 gcc_jit_context
* gcc_context
;
22 gcc_jit_block
* gcc_block
;
23 gcc_jit_result
* gcc_result
;
26 static void printcontext(oberon_context_t
* ctx
, char * s
)
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;
34 printf(" ctx = %p:\n", ctx);
35 printf(" gctx = %p:\n", gctx);
36 printf(" context = %p:\n", context);
37 printf(" block = %p:\n", block);
41 // =======================================================================
43 // =======================================================================
46 oberon_generator_init_context(oberon_context_t
* ctx
)
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");
61 oberon_generator_destroy_context(oberon_context_t
* ctx
)
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
);
72 oberon_generator_init_type(oberon_context_t
* ctx
, oberon_type_t
* type
)
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
)
82 gen_type
= gcc_jit_context_get_int_type(gcc_context
, type
-> size
, 1);
84 else if(type
-> class == OBERON_TYPE_BOOLEAN
)
86 gen_type
= gcc_jit_context_get_type(gcc_context
, GCC_JIT_TYPE_BOOL
);
90 oberon_error(ctx
, "oberon_generator_init_type: invalid type class %i", type
-> class);
93 type
-> gen_type
= gen_type
;
97 oberon_generator_init_var(oberon_context_t
* ctx
, oberon_object_t
* var
)
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
;
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
131 proc
-> gen_proc
= gen_proc
;
134 // =======================================================================
136 // =======================================================================
138 static gcc_jit_rvalue
* rvalue_from_expr(oberon_context_t
* ctx
, oberon_expr_t
* expr
);
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
152 gcc_jit_block
* gcc_block
= gcc_jit_function_new_block(func
, NULL
);
154 gen_context
-> gcc_block
= gcc_block
;
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
;
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
;
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
);
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
;
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
;
221 oberon_error(ctx
, "invalid lvalue expression");
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
);
250 right
= gcc_jit_context_one(gcc_context
, bool_type
);
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
);
261 gcc_jit_function
* func
= item
-> var
-> gen_proc
;
262 right
= gcc_jit_context_new_call(
263 gcc_context
, NULL
, func
, 0, NULL
268 oberon_error(ctx
, "oberon_generate_push: invalid mode %i", item
-> mode
);
275 int type
; // 0 - unary, 1 - binary, 2 - comp
277 enum gcc_jit_unary_op unary_op
;
278 enum gcc_jit_binary_op binary_op
;
279 enum gcc_jit_comparison comp_op
;
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
}
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
;
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
);
332 oberon_error(ctx
, "rvalue_from_operator: wat");
338 static gcc_jit_rvalue
*
339 rvalue_from_expr(oberon_context_t
* ctx
, oberon_expr_t
* expr
)
341 gcc_jit_rvalue
* right
;
345 oberon_item_t
* item
= (oberon_item_t
*) expr
;
346 right
= rvalue_from_item(ctx
, item
);
350 oberon_oper_t
* operator = (oberon_oper_t
*) expr
;
351 right
= rvalue_from_operator(ctx
, operator);
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
);
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");