X-Git-Url: https://deadsoftware.ru/gitweb?a=blobdiff_plain;f=generator.c;h=07e7bc470ee1b1fb9a337810e695fce530bf16d3;hb=90ad7d921e60c24b11bc08cd173c0e1c80f9b06d;hp=c633e542131722832c5d586e732e18d7f04d85f2;hpb=c3449e207b5e1e85ecea55975163a4dc6b986962;p=dsw-obn.git diff --git a/generator.c b/generator.c index c633e54..07e7bc4 100644 --- a/generator.c +++ b/generator.c @@ -11,9 +11,9 @@ #include /* - * oberon_var_t -> gvar == gcc_jit_lvalue; - * oberon_type_t -> gtype == gcc_jit_type; - * oberon_context_t -> gctx == gen_context_t; + * oberon_object_t -> gen_var == gcc_jit_lvalue; + * oberon_type_t -> gen_type == gcc_jit_type; + * oberon_context_t -> gen_context == gen_context_t; */ typedef struct @@ -94,9 +94,10 @@ oberon_generator_init_type(oberon_context_t * ctx, oberon_type_t * type) } void -oberon_generator_init_var(oberon_context_t * ctx, oberon_var_t * var) +oberon_generator_init_var(oberon_context_t * ctx, oberon_object_t * var) { printcontext(ctx, "oberon_generator_init_var"); + assert(var -> class == OBERON_CLASS_VAR); gen_context_t * gen_context = ctx -> gen_context; gcc_jit_context * gcc_context = gen_context -> gcc_context; @@ -109,30 +110,137 @@ oberon_generator_init_var(oberon_context_t * ctx, oberon_var_t * var) var -> gen_var = gen_var; } +void +oberon_generator_init_proc(oberon_context_t * ctx, oberon_object_t * proc) +{ + assert(proc -> class == OBERON_CLASS_PROC); + + gen_context_t * gen_context = ctx -> gen_context; + gcc_jit_context * gcc_context = gen_context -> gcc_context; + //gcc_jit_type * gen_type = proc -> type -> gen_type; + const char * name = proc -> name; + + gcc_jit_function * gen_proc; + + // TODO make real signature + gcc_jit_type * void_type = gcc_jit_context_get_type(gcc_context, GCC_JIT_TYPE_VOID); + gen_proc = gcc_jit_context_new_function( + gcc_context, NULL, GCC_JIT_FUNCTION_EXPORTED, void_type, name, 0, NULL, 0 + ); + + proc -> gen_proc = gen_proc; +} + // ======================================================================= // GENERATOR // ======================================================================= -static gcc_jit_rvalue * -oberon_generate_rvalue_from_item(oberon_context_t * ctx, oberon_item_t * item) +static gcc_jit_rvalue * rvalue_from_expr(oberon_context_t * ctx, oberon_expr_t * expr); + +void +oberon_generate_begin_module(oberon_context_t * ctx) { - printcontext(ctx, "oberon_generate_rvalue_from_item"); + 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; +} + +void +oberon_generate_begin_proc(oberon_context_t * ctx, oberon_object_t * proc) +{ + gen_context_t * gen_context = ctx -> gen_context; + + gcc_jit_function * func = proc -> gen_proc; + gcc_jit_block * gcc_block = gcc_jit_function_new_block(func, NULL); + + // TODO make stack for block + gen_context -> gcc_block = gcc_block; +} + +void +oberon_generate_call_proc(oberon_context_t * ctx, oberon_expr_t * desig) +{ + gen_context_t * gen_context = ctx -> gen_context; + gcc_jit_block * block = gen_context -> gcc_block; + + gcc_jit_rvalue * return_value; + return_value = rvalue_from_expr(ctx, desig); + gcc_jit_block_add_eval(block, NULL, return_value); +} + +void +oberon_generate_end_proc(oberon_context_t * ctx) +{ + 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) +{ + 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_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; + gcc_jit_rvalue * right; if(item -> mode == MODE_VAR) { + assert(item -> var -> class == OBERON_CLASS_VAR); 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 +253,15 @@ 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 if(item -> mode == MODE_CALL) + { + assert(item -> var -> class == OBERON_CLASS_PROC); + /* TODO args */ + gcc_jit_function * func = item -> var -> gen_proc; + right = gcc_jit_context_new_call( + gcc_context, NULL, func, 0, NULL + ); } else { @@ -155,59 +271,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; + left = lvalue_from_expr(ctx, dst); - right = oberon_generate_rvalue_from_item(ctx, src); - - 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); }