From 2d029d2c2b27639e3a2b6c43e63788b00110818e Mon Sep 17 00:00:00 2001 From: DeaDDooMER Date: Mon, 24 Jul 2017 22:37:09 +0300 Subject: [PATCH] =?utf8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD?= =?utf8?q?=D1=8B=20=D0=BB=D0=BE=D0=BA=D0=B0=D0=BB=D1=8C=D0=BD=D1=8B=D0=B5?= =?utf8?q?=20=D0=BE=D0=B1=D1=8A=D1=8F=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- generator.c | 61 ++++++++++++++++++++++++++++++++++++++++------------- notes | 14 ++++++------ oberon.c | 47 ++++++++++++++++++++++++++++++++--------- oberon.h | 61 +++++++++++++++++++++++++++++++++-------------------- test.c | 4 ++++ 5 files changed, 133 insertions(+), 54 deletions(-) diff --git a/generator.c b/generator.c index 4c3a984..419a2b2 100644 --- a/generator.c +++ b/generator.c @@ -8,8 +8,6 @@ #include "oberon.h" #include "generator.h" -#include - static void printcontext(oberon_context_t * ctx, char * s) { /* @@ -29,6 +27,24 @@ static void printcontext(oberon_context_t * ctx, char * s) // ALLOC // ======================================================================= +static void +oberon_generator_open_block(gen_context_t * gen_context, gcc_jit_block * gcc_block) +{ + gen_block_t * block = malloc(sizeof *block); + memset(block, 0, sizeof *block); + + block -> gcc_block = gcc_block; + block -> up = gen_context -> block; + + gen_context -> block = block; +} + +static void +oberon_generator_close_block(gen_context_t * gen_context) +{ + gen_context -> block = gen_context -> block -> up; +} + void oberon_generator_init_context(oberon_context_t * ctx) { @@ -170,9 +186,19 @@ oberon_generator_init_var(oberon_context_t * ctx, oberon_object_t * var) gcc_jit_field * gcc_field = NULL; if(var -> class == OBERON_CLASS_VAR) { - gcc_lvalue = gcc_jit_context_new_global( - gcc_context, NULL, GCC_JIT_GLOBAL_INTERNAL, gcc_type, name - ); + if(var -> local) + { + gen_proc_t * gen_func = var -> parent -> gen_proc; + gcc_jit_function * func = gen_func -> gcc_func; + + gcc_lvalue = gcc_jit_function_new_local(func, NULL, gcc_type, name); + } + else + { + gcc_lvalue = gcc_jit_context_new_global( + gcc_context, NULL, GCC_JIT_GLOBAL_INTERNAL, gcc_type, name + ); + } } else if(var -> class == OBERON_CLASS_PARAM) { @@ -202,7 +228,10 @@ oberon_generator_init_var(oberon_context_t * ctx, oberon_object_t * var) void oberon_generator_init_proc(oberon_context_t * ctx, oberon_object_t * proc) { - assert(proc -> class == OBERON_CLASS_PROC); + if(proc -> local) + { + oberon_error(ctx, "generator: local procedures not supported"); + } gen_context_t * gen_context = ctx -> gen_context; gcc_jit_context * gcc_context = gen_context -> gcc_context; @@ -255,7 +284,7 @@ oberon_generate_begin_module(oberon_context_t * ctx) ); gcc_jit_block * gcc_block = gcc_jit_function_new_block(func, NULL); - gen_context -> gcc_block = gcc_block; + oberon_generator_open_block(gen_context, gcc_block); } void @@ -264,11 +293,11 @@ 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 * gcc_block = gen_context -> block -> gcc_block; gcc_jit_block_end_with_void_return(gcc_block, NULL); - gen_context -> gcc_block = NULL; + oberon_generator_close_block(gen_context); } void @@ -280,15 +309,15 @@ oberon_generate_begin_proc(oberon_context_t * ctx, oberon_object_t * proc) gcc_jit_function * func = gen_proc -> gcc_func; gcc_jit_block * gcc_block = gcc_jit_function_new_block(func, NULL); - // TODO make stack for block - gen_context -> gcc_block = gcc_block; + oberon_generator_open_block(gen_context, 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; + gen_block_t * gen_block = gen_context -> block; + gcc_jit_block * block = gen_block -> gcc_block; gcc_jit_rvalue * return_value; return_value = rvalue_from_expr(ctx, desig); @@ -299,14 +328,15 @@ void oberon_generate_end_proc(oberon_context_t * ctx) { gen_context_t * gen_context = ctx -> gen_context; - gen_context -> gcc_block = NULL; + oberon_generator_close_block(gen_context); } void oberon_generate_return(oberon_context_t * ctx, oberon_expr_t * expr) { gen_context_t * gen_context = ctx -> gen_context; - gcc_jit_block * gcc_block = gen_context -> gcc_block; + gen_block_t * gen_block = gen_context -> block; + gcc_jit_block * gcc_block = gen_block -> gcc_block; if(expr == NULL) { @@ -584,7 +614,8 @@ oberon_generate_assign(oberon_context_t * ctx, oberon_expr_t * src, oberon_expr_ } gen_context_t * gen_context = ctx -> gen_context; - gcc_jit_block * gcc_block = gen_context -> gcc_block; + gen_block_t * gen_block = gen_context -> block; + gcc_jit_block * gcc_block = gen_block -> gcc_block; gcc_jit_block_add_assignment(gcc_block, NULL, left, right); } diff --git a/notes b/notes index 0ef7b20..2bf0b29 100644 --- a/notes +++ b/notes @@ -1,16 +1,18 @@ -- локальные переменные создаются как глобальные -- сегфолт при создании локальной процедуры +- не реализованы объявления процедур наперёд - нету процедуры NEW -- не реализовано расширение типа record - нету открытых массивов -- не работает присваивание к переменным-процедурам. +- нету секции import + - не понятен результат присваивания статических структур (* reca := recb; *) - не понятен результат присваивания статических массивов (* arr1 := arr2; *) -- не реализованы процедуры "наперёд" - нету типа set - не реализована свёртка констант -- не реализован автокаст (libgccjit сам разруливает) - не протестированы типы разнных размеров + +- не реализовано расширение типа record +- не работает присваивание к переменным-процедурам. +- не реализован автокаст (libgccjit сам разруливает) +- libgccjit не умеет в локальные функции (опять пилить костыли как в jvm) diff --git a/oberon.c b/oberon.c index 3837bf5..ac695d3 100644 --- a/oberon.c +++ b/oberon.c @@ -118,6 +118,12 @@ oberon_open_scope(oberon_context_t * ctx) scope -> list = list; scope -> up = ctx -> decl; + if(scope -> up) + { + scope -> parent = scope -> up -> parent; + scope -> local = scope -> up -> local; + } + ctx -> decl = scope; return scope; } @@ -147,6 +153,8 @@ oberon_define_object(oberon_scope_t * scope, char * name, int class) memset(newvar, 0, sizeof *newvar); newvar -> name = name; newvar -> class = class; + newvar -> local = scope -> local; + newvar -> parent = scope -> parent; x -> next = newvar; @@ -156,6 +164,8 @@ oberon_define_object(oberon_scope_t * scope, char * name, int class) static void oberon_define_field(oberon_context_t * ctx, oberon_type_t * rec, char * name, oberon_type_t * type) { + // TODO check base fields + oberon_object_t * x = rec -> decl; while(x -> next && strcmp(x -> next -> name, name) != 0) { @@ -172,6 +182,8 @@ oberon_define_field(oberon_context_t * ctx, oberon_type_t * rec, char * name, o field -> name = name; field -> class = OBERON_CLASS_FIELD; field -> type = type; + field -> local = 1; + field -> parent = NULL; rec -> num_decl += 1; x -> next = field; @@ -1259,6 +1271,7 @@ oberon_const_expr(oberon_context_t * ctx) static void oberon_decl_seq(oberon_context_t * ctx); static void oberon_statement_seq(oberon_context_t * ctx); +static void oberon_initialize_decl(oberon_context_t * ctx); static void oberon_expect_token(oberon_context_t * ctx, int token) @@ -1391,7 +1404,10 @@ oberon_opt_formal_pars(oberon_context_t * ctx, oberon_type_t ** type) static void oberon_make_return(oberon_context_t * ctx, oberon_expr_t * expr) { - if(ctx -> result_type -> class == OBERON_TYPE_VOID) + oberon_object_t * proc = ctx -> decl -> parent; + oberon_type_t * result_type = proc -> type -> base; + + if(result_type -> class == OBERON_TYPE_VOID) { if(expr != NULL) { @@ -1405,10 +1421,10 @@ oberon_make_return(oberon_context_t * ctx, oberon_expr_t * expr) oberon_error(ctx, "procedure requires expression on result"); } - oberon_autocast_to(ctx, expr, ctx -> result_type); + oberon_autocast_to(ctx, expr, result_type); } - ctx -> has_return = 1; + proc -> has_return = 1; oberon_generate_return(ctx, expr); } @@ -1423,6 +1439,7 @@ oberon_proc_decl(oberon_context_t * ctx) oberon_scope_t * this_proc_def_scope = ctx -> decl; oberon_open_scope(ctx); + ctx -> decl -> local = 1; oberon_type_t * signature; signature = oberon_new_type_ptr(OBERON_TYPE_VOID); @@ -1431,14 +1448,16 @@ oberon_proc_decl(oberon_context_t * ctx) oberon_object_t * proc; proc = oberon_define_proc(this_proc_def_scope, name, signature); - ctx -> result_type = signature -> base; - ctx -> has_return = 0; + // процедура как новый родительский объект + ctx -> decl -> parent = proc; + + oberon_initialize_decl(ctx); + oberon_generator_init_proc(ctx, proc); oberon_assert_token(ctx, SEMICOLON); oberon_decl_seq(ctx); oberon_generator_init_type(ctx, signature); - oberon_generator_init_proc(ctx, proc); oberon_generate_begin_proc(ctx, proc); @@ -1460,11 +1479,10 @@ oberon_proc_decl(oberon_context_t * ctx) oberon_make_return(ctx, NULL); } - if(ctx -> has_return == 0) + if(proc -> has_return == 0) { oberon_error(ctx, "procedure requires return"); } - ctx -> result_type = NULL; oberon_generate_end_proc(ctx); oberon_close_scope(ctx -> decl); @@ -1917,7 +1935,13 @@ oberon_initialize_type(oberon_context_t * ctx, oberon_type_t * type) static void oberon_initialize_object(oberon_context_t * ctx, oberon_object_t * x) { - printf("oberon_initialize_object: name %s class %i\n", x -> name, x -> class); + if(x -> initialized) + { + return; + } + + x -> initialized = 1; + switch(x -> class) { case OBERON_CLASS_TYPE: @@ -2006,7 +2030,10 @@ oberon_make_call(oberon_context_t * ctx, oberon_expr_t * desig) { if(desig -> result -> class != OBERON_TYPE_VOID) { - oberon_error(ctx, "procedure with result"); + if(desig -> result -> class != OBERON_TYPE_PROCEDURE) + { + oberon_error(ctx, "procedure with result"); + } } oberon_autocast_call(ctx, desig); diff --git a/oberon.h b/oberon.h index 02547cd..9d17afd 100644 --- a/oberon.h +++ b/oberon.h @@ -3,34 +3,42 @@ #include -/* - * Стуктуры данных генератора - */ +typedef struct gen_proc_s gen_proc_t; +typedef struct gen_type_s gen_type_t; +typedef struct gen_var_s gen_var_t; +typedef struct gen_block_s gen_block_t; +typedef struct gen_context_s gen_context_t; -typedef struct +struct gen_proc_s { - gcc_jit_function * gcc_func; -} gen_proc_t; + gcc_jit_function * gcc_func; +}; -typedef struct +struct gen_type_s { - gcc_jit_type * gcc_type; - gcc_jit_struct * gcc_struct; -} gen_type_t; + gcc_jit_type * gcc_type; + gcc_jit_struct * gcc_struct; +}; -typedef struct +struct gen_var_s { - gcc_jit_lvalue * gcc_lvalue; - gcc_jit_param * gcc_param; - gcc_jit_field * gcc_field; -} gen_var_t; + gcc_jit_lvalue * gcc_lvalue; + gcc_jit_param * gcc_param; + gcc_jit_field * gcc_field; +}; -typedef struct +struct gen_block_s { - gcc_jit_context * gcc_context; - gcc_jit_block * gcc_block; - gcc_jit_result * gcc_result; -} gen_context_t; + gcc_jit_block * gcc_block; + gen_block_t * up; +}; + +struct gen_context_s +{ + gcc_jit_context * gcc_context; + gcc_jit_result * gcc_result; + gen_block_t * block; +}; typedef struct oberon_type_s oberon_type_t; typedef struct oberon_object_s oberon_object_t; @@ -57,6 +65,9 @@ struct oberon_scope_s oberon_context_t * ctx; oberon_object_t * list; oberon_scope_t * up; + + oberon_object_t * parent; + int local; }; /* @@ -142,7 +153,14 @@ struct oberon_object_s char * name; int class; + int local; int linked; + int initialized; + + oberon_object_t * parent; + int has_return; // for proc + + oberon_type_t * type; oberon_item_t * value; oberon_object_t * next; @@ -195,9 +213,6 @@ struct oberon_context_s char * string; int integer; - int has_return; - oberon_type_t * result_type; - oberon_scope_t * decl; oberon_module_t * mod; diff --git a/test.c b/test.c index 2c29667..44b8465 100644 --- a/test.c +++ b/test.c @@ -4,11 +4,15 @@ static const char source[] = "MODULE Test;" + "TYPE" + " Rec = RECORD i : INTEGER; END;" "VAR" " i : INTEGER;" " j : INTEGER;" "" "PROCEDURE Tier(VAR x : INTEGER);" + "VAR" + " z : INTEGER;" "BEGIN;" " x := i;" "END Tier;" -- 2.29.2