11 #include <libgccjit.h>
14 * oberon_var_t -> gvar == gcc_jit_lvalue;
15 * oberon_type_t -> gtype == gcc_jit_type;
16 * oberon_context_t -> gctx == 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_var_t
* var
)
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 // =======================================================================
114 // =======================================================================
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
128 gcc_jit_block
* gcc_block
= gcc_jit_function_new_block(func
, NULL
);
130 gen_context
-> gcc_block
= gcc_block
;
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
;
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
;
163 oberon_error(ctx
, "invalid lvalue expression");
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
);
193 right
= gcc_jit_context_one(gcc_context
, bool_type
);
197 right
= gcc_jit_context_zero(gcc_context
, bool_type
);
202 oberon_error(ctx
, "oberon_generate_push: invalid mode %i", item
-> mode
);
209 int type
; // 0 - unary, 1 - binary, 2 - comp
211 enum gcc_jit_unary_op unary_op
;
212 enum gcc_jit_binary_op binary_op
;
213 enum gcc_jit_comparison comp_op
;
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
}
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
;
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
);
266 oberon_error(ctx
, "rvalue_from_operator: wat");
272 static gcc_jit_rvalue
*
273 rvalue_from_expr(oberon_context_t
* ctx
, oberon_expr_t
* expr
)
275 gcc_jit_rvalue
* right
;
279 oberon_item_t
* item
= (oberon_item_t
*) expr
;
280 right
= rvalue_from_item(ctx
, item
);
284 oberon_oper_t
* operator = (oberon_oper_t
*) expr
;
285 right
= rvalue_from_operator(ctx
, operator);
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
);
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");