X-Git-Url: https://deadsoftware.ru/gitweb?a=blobdiff_plain;f=generator.c;h=21506b0626fe5db7cfbd117a444d2295de3448a2;hb=390a7e053165954865bc013a7c7057982c206453;hp=c633e542131722832c5d586e732e18d7f04d85f2;hpb=c3449e207b5e1e85ecea55975163a4dc6b986962;p=dsw-obn.git diff --git a/generator.c b/generator.c index c633e54..21506b0 100644 --- a/generator.c +++ b/generator.c @@ -113,11 +113,64 @@ oberon_generator_init_var(oberon_context_t * ctx, oberon_var_t * var) // GENERATOR // ======================================================================= -static gcc_jit_rvalue * -oberon_generate_rvalue_from_item(oberon_context_t * ctx, oberon_item_t * item) +void +oberon_generate_begin_module(oberon_context_t * ctx) +{ + printcontext(ctx, "oberon_generate_begin_module"); + + gen_context_t * gen_context = ctx -> gen_context; + gcc_jit_context * gcc_context = gen_context -> gcc_context; + + gcc_jit_type * void_type = gcc_jit_context_get_type(gcc_context, GCC_JIT_TYPE_VOID); + gcc_jit_function * func = gcc_jit_context_new_function( + gcc_context, NULL, GCC_JIT_FUNCTION_EXPORTED, void_type, "BEGIN", 0, NULL, 0 + ); + gcc_jit_block * gcc_block = gcc_jit_function_new_block(func, NULL); + + gen_context -> gcc_block = gcc_block; +} + +void +oberon_generate_end_module(oberon_context_t * ctx) +{ + printcontext(ctx, "oberon_generate_end_module"); + + gen_context_t * gen_context = ctx -> gen_context; + gcc_jit_block * gcc_block = gen_context -> gcc_block; + + gcc_jit_block_end_with_void_return(gcc_block, NULL); + + gen_context -> gcc_block = NULL; +} + +static gcc_jit_lvalue * +lvalue_from_expr(oberon_context_t *ctx, oberon_expr_t * expr) { - printcontext(ctx, "oberon_generate_rvalue_from_item"); + gcc_jit_lvalue * left; + oberon_item_t * item; + + if(expr -> is_item) + { + item = (oberon_item_t *) expr; + if(item -> mode != MODE_VAR) + { + oberon_error(ctx, "invalid lvalue expression"); + } + left = item -> var -> gen_var; + } + else + { + oberon_error(ctx, "invalid lvalue expression"); + } + + return left; +} +static gcc_jit_rvalue * rvalue_from_expr(oberon_context_t * ctx, oberon_expr_t * expr); + +static gcc_jit_rvalue * +rvalue_from_item(oberon_context_t * ctx, oberon_item_t * item) +{ gen_context_t * gen_context = ctx -> gen_context; gcc_jit_context * gcc_context = gen_context -> gcc_context; @@ -126,13 +179,11 @@ oberon_generate_rvalue_from_item(oberon_context_t * ctx, oberon_item_t * item) { gcc_jit_lvalue * gen_var = item -> var -> gen_var; right = gcc_jit_lvalue_as_rvalue(gen_var); - printf("PUSH (var) %s\n", item -> var -> name); } else if(item -> mode == MODE_INTEGER) { gcc_jit_type * int_type = gcc_jit_context_get_type(gcc_context, GCC_JIT_TYPE_INT); right = gcc_jit_context_new_rvalue_from_int(gcc_context, int_type, item -> integer); - printf("PUSH (int) %i\n", item -> integer); } else if(item -> mode == MODE_BOOLEAN) { @@ -145,7 +196,6 @@ oberon_generate_rvalue_from_item(oberon_context_t * ctx, oberon_item_t * item) { right = gcc_jit_context_zero(gcc_context, bool_type); } - printf("PUSH (bool) %i\n", item -> boolean); } else { @@ -155,59 +205,100 @@ oberon_generate_rvalue_from_item(oberon_context_t * ctx, oberon_item_t * item) return right; } -void -oberon_generate_begin_module(oberon_context_t * ctx) +struct { + int type; // 0 - unary, 1 - binary, 2 - comp + union { + enum gcc_jit_unary_op unary_op; + enum gcc_jit_binary_op binary_op; + enum gcc_jit_comparison comp_op; + }; +} op_table[] = { + { 0, .unary_op = GCC_JIT_UNARY_OP_LOGICAL_NEGATE }, + { 0, .unary_op = GCC_JIT_UNARY_OP_MINUS }, + + { 1, .binary_op = GCC_JIT_BINARY_OP_PLUS }, + { 1, .binary_op = GCC_JIT_BINARY_OP_MINUS }, + { 1, .binary_op = GCC_JIT_BINARY_OP_DIVIDE }, + { 1, .binary_op = GCC_JIT_BINARY_OP_MODULO }, + { 1, .binary_op = GCC_JIT_BINARY_OP_LOGICAL_AND }, + { 1, .binary_op = GCC_JIT_BINARY_OP_LOGICAL_OR }, + + { 2, .comp_op = GCC_JIT_COMPARISON_EQ }, + { 2, .comp_op = GCC_JIT_COMPARISON_NE }, + { 2, .comp_op = GCC_JIT_COMPARISON_LT }, + { 2, .comp_op = GCC_JIT_COMPARISON_LE }, + { 2, .comp_op = GCC_JIT_COMPARISON_GT }, + { 2, .comp_op = GCC_JIT_COMPARISON_GE } +}; + +static gcc_jit_rvalue * +rvalue_from_operator(oberon_context_t * ctx, oberon_oper_t * operator) { - printcontext(ctx, "oberon_generate_begin_module"); + gcc_jit_rvalue * right; gen_context_t * gen_context = ctx -> gen_context; gcc_jit_context * gcc_context = gen_context -> gcc_context; + gcc_jit_type * result_type = operator -> result -> gen_type; - gcc_jit_type * void_type = gcc_jit_context_get_type(gcc_context, GCC_JIT_TYPE_VOID); - gcc_jit_function * func = gcc_jit_context_new_function( - gcc_context, NULL, GCC_JIT_FUNCTION_EXPORTED, void_type, "BEGIN", 0, NULL, 0 - ); - gcc_jit_block * gcc_block = gcc_jit_function_new_block(func, NULL); + int expr_type = op_table[operator -> op].type; + if(expr_type == 0) + { + enum gcc_jit_unary_op op = op_table[operator -> op].unary_op; + gcc_jit_rvalue * l = rvalue_from_expr(ctx, operator -> left); + right = gcc_jit_context_new_unary_op(gcc_context, NULL, op, result_type, l); + } + else if(expr_type == 1) + { + enum gcc_jit_unary_op op = op_table[operator -> op].binary_op; + gcc_jit_rvalue * l = rvalue_from_expr(ctx, operator -> left); + gcc_jit_rvalue * r = rvalue_from_expr(ctx, operator -> right); + right = gcc_jit_context_new_binary_op(gcc_context, NULL, op, result_type, l, r); + } + else if(expr_type == 2) + { + enum gcc_jit_comparison op = op_table[operator -> op].comp_op; + gcc_jit_rvalue * l = rvalue_from_expr(ctx, operator -> left); + gcc_jit_rvalue * r = rvalue_from_expr(ctx, operator -> right); + right = gcc_jit_context_new_comparison(gcc_context, NULL, op, l, r); + } + else + { + oberon_error(ctx, "rvalue_from_operator: wat"); + } - gen_context -> gcc_block = gcc_block; + return right; } -void -oberon_generate_end_module(oberon_context_t * ctx) +static gcc_jit_rvalue * +rvalue_from_expr(oberon_context_t * ctx, oberon_expr_t * expr) { - printcontext(ctx, "oberon_generate_end_module"); - - gen_context_t * gen_context = ctx -> gen_context; - gcc_jit_block * gcc_block = gen_context -> gcc_block; + gcc_jit_rvalue * right; - gcc_jit_block_end_with_void_return(gcc_block, NULL); + if(expr -> is_item) + { + oberon_item_t * item = (oberon_item_t *) expr; + right = rvalue_from_item(ctx, item); + } + else + { + oberon_oper_t * operator = (oberon_oper_t *) expr; + right = rvalue_from_operator(ctx, operator); + } - gen_context -> gcc_block = NULL; + return right; } void -oberon_generate_assign(oberon_context_t * ctx, oberon_item_t * src, oberon_item_t * dst) +oberon_generate_assign(oberon_context_t * ctx, oberon_expr_t * src, oberon_expr_t * dst) { - printcontext(ctx, "oberon_generate_assign"); - - gen_context_t * gen_context = ctx -> gen_context; - gcc_jit_block * gcc_block = gen_context -> gcc_block; - gcc_jit_lvalue * left; - gcc_jit_rvalue * right; - - right = oberon_generate_rvalue_from_item(ctx, src); + left = lvalue_from_expr(ctx, dst); - if(dst -> mode == MODE_VAR) - { - printf("STORE %s\n", dst -> var -> name); - left = dst -> var -> gen_var; - } - else - { - oberon_error(ctx, "oberon_generate_assign: invalid assignment"); - } + gcc_jit_rvalue * right; + right = rvalue_from_expr(ctx, src); + gen_context_t * gen_context = ctx -> gen_context; + gcc_jit_block * gcc_block = gen_context -> gcc_block; gcc_jit_block_add_assignment(gcc_block, NULL, left, right); }