From: DeaDDooMER Date: Mon, 24 Jul 2017 20:04:11 +0000 (+0300) Subject: Добавлено вычисление размеров типа для аллокации X-Git-Url: http://deadsoftware.ru/gitweb?p=dsw-obn.git;a=commitdiff_plain;h=12ae486a18746b042fcc4ebbefc5449d4d3464af Добавлено вычисление размеров типа для аллокации --- diff --git a/generator.c b/generator.c index 94bc169..179320a 100644 --- a/generator.c +++ b/generator.c @@ -4,6 +4,7 @@ #include #include #include +#include #include @@ -19,6 +20,7 @@ __OBERON_ALLOC__ (size_t bytes) { void * p = GC_MALLOC(bytes); memset(p, 0, bytes); + printf("allocated %lu bytes\n", bytes); return p; } @@ -323,10 +325,50 @@ static gcc_jit_rvalue * rvalue_from_item(oberon_context_t * ctx, oberon_item_t * static gcc_jit_rvalue * rvalue_from_expr(oberon_context_t * ctx, oberon_expr_t * expr); static int -oberon_generator_get_type_size(oberon_type_t * type) +oberon_generator_get_type_size(oberon_context_t * ctx, oberon_type_t * type) { - printf("TODO: oberon_generator_get_type_size\n"); - return 128; + int size = 0; + switch(type -> class) + { + case OBERON_TYPE_INTEGER: + size = type -> size; + printf("int size: %i\n", size); + break; + case OBERON_TYPE_BOOLEAN: + size = sizeof(bool); + printf("bool size: %i\n", size); + break; + case OBERON_TYPE_PROCEDURE: + case OBERON_TYPE_POINTER: + size = sizeof(void*); + printf("ptr size: %i\n", size); + break; + case OBERON_TYPE_ARRAY: + size = type -> size; + type = type -> base; + size *= oberon_generator_get_type_size(ctx, type); + printf("array size: %i\n", size); + break; + case OBERON_TYPE_RECORD: + { + int num = type -> num_decl; + oberon_object_t * arg = type -> decl; + for(int i = 0; i < num; i++) + { + oberon_type_t * x; + x = arg -> type; + size += oberon_generator_get_type_size(ctx, x); + arg = arg -> next; + } + } + printf("struct size: %i\n", size); + break; + default: + oberon_error(ctx, "oberon_generator_get_type_size: wat"); + break; + } + + return size; } void @@ -578,9 +620,12 @@ rvalue_from_item(oberon_context_t * ctx, oberon_item_t * item) gcc_jit_type * type = gcc_jit_context_get_type(gcc_context, GCC_JIT_TYPE_VOID_PTR); right = gcc_jit_context_null(gcc_context, type); } - else if(item -> mode == MODE_NEWARR) + else if(item -> mode == MODE_NEW) { - int type_size = oberon_generator_get_type_size(item -> type); + assert(item -> result -> class == OBERON_TYPE_POINTER); + + oberon_type_t * type = item -> result -> base; + int type_size = oberon_generator_get_type_size(ctx, type); int array_size = type_size; int num = item -> num_args; diff --git a/notes b/notes index 977d7cd..d8331b1 100644 --- a/notes +++ b/notes @@ -1,30 +1,46 @@ -- размеры типов не вычисляются (oberon_generator_get_type_size) - в libgccjit нет средств получения размера типов, в т.ч. структур - Придётся гадать. -- процедура NEW создаёт массивы только статической размерности (и не создаёт структуры). +- нету типа real, оператор / должен возвращать дробный результат - нету открытых массивов +- нет символов и строк - нету операторов if, while и т.д. -- нет символов и строк - импортируемые модули не инициализируются (секция begin) -- нету типа real, оператор / должен возвращать дробный результат - нету типа set - не реализована свёртка констант - не протестированы типы разнных размеров +- не реализовано расширение типа record: + libgccjit не умеет в классы. Проверки в рантайме надо делать вручную. +- нет проверок границ массивов в рантайме: + Потому что как минимум нет дескрипторов типа. + Возможно можно заюзать это: + https://gcc.gnu.org/onlinedocs/gcc/Pointer-Bounds-Checker-builtins.html +- При вычислении размера структур не учитывается вравнивание. + в libgccjit нет средств получения размера типов, в т.ч. структур + Как происходит выравнивание и есть ли оно вообще по дефолту - не понятно: + Нужно ли для получения выровненных структур использовать gcc_jit_type_get_aligned? + Пересекается с этим: + https://gcc.gnu.org/onlinedocs/gcc/Common-Type-Attributes.html + Требуемые выравнивания для типов можно получить через встроинную функцию __alignof__(T) + https://gcc.gnu.org/onlinedocs/gcc/Alignment.html + Возможный алгоритм выравнивания: + https://stackoverflow.com/questions/6963998/how-does-gcc-calculate-the-required-space-for-a-structure + http://www.rendoc.tech/questions/834444/how-does-gcc-calculate-the-required-space-for-a-structure + Есть ещё что-то для проверки границ объектов: + https://gcc.gnu.org/onlinedocs/gcc/Object-Size-Checking.html +- не понятен результат присваивания статических/разыменованных структур и массивов + (* reca := recb; *) - побайтовое копирование? - не реализовано присваивание процедур к переменным-процедурам: в libgccjit нет средств получения указателя на функцию. Как решение-костыль - получение указателя в основной программе и сохранение в переменной. -- не реализовано расширение типа record: - libgccjit не умеет в классы. Проверки в рантайме надо делать вручную. - не реализован автокаст: Не критично: libgccjit сам разруливает типы разных размеров. - не реализованы локальные процедуры: libgccjit не умеет в локальные функции. Обойти можно костылём как в jvm. -- не понятен результат присваивания статических/разыменованных структур (* reca := recb; *) -- не понятен результат присваивания статических/разыменованных массивов (* arr1 := arr2; *) +- нет проверок переполнения как в рантайме, так и в компилтайме. + Возможно можно заюзать это: + https://gcc.gnu.org/onlinedocs/gcc/Integer-Overflow-Builtins.html - нету счёта строк / столбцов - любая ошибка фатальна diff --git a/oberon.c b/oberon.c index 931d948..dab60b0 100644 --- a/oberon.c +++ b/oberon.c @@ -2602,16 +2602,19 @@ oberon_make_new_call(oberon_context_t * ctx, int num_args, oberon_expr_t * list_ type = type -> base; oberon_expr_t * src; + src = oberon_new_item(MODE_NEW, dst -> result, 0); + src -> item.num_args = 0; + src -> item.args = NULL; + if(type -> class == OBERON_TYPE_ARRAY) { + // Пригодится при работе с открытыми массивами + /* int dim = 1; - oberon_expr_t * sizes = NULL; oberon_expr_t * last_size = NULL; - sizes = last_size = oberon_new_item(MODE_INTEGER, ctx -> int_type, 1); sizes -> item.integer = type -> size; - oberon_type_t * base = type -> base; while(base -> class == OBERON_TYPE_ARRAY) { @@ -2624,13 +2627,12 @@ oberon_make_new_call(oberon_context_t * ctx, int num_args, oberon_expr_t * list_ base = base -> base; dim += 1; } + */ - src = oberon_new_item(MODE_NEWARR, dst -> result, 0); - src -> item.num_args = dim; - src -> item.args = sizes; - src -> item.type = base; + src -> item.num_args = 0; + src -> item.args = NULL; } - else + else if(type -> class != OBERON_TYPE_RECORD) { oberon_error(ctx, "oberon_make_new_call: wat"); } diff --git a/oberon.h b/oberon.h index 4b78545..53693a7 100644 --- a/oberon.h +++ b/oberon.h @@ -259,7 +259,7 @@ enum MODE_FIELD, MODE_DEREF, MODE_NIL, - MODE_NEWARR + MODE_NEW }; enum @@ -304,7 +304,6 @@ struct oberon_item_s int num_args; oberon_expr_t * args; - oberon_type_t * type; }; struct oberon_oper_s diff --git a/test.c b/test.c index fc00333..1f44077 100644 --- a/test.c +++ b/test.c @@ -11,7 +11,8 @@ static char source_test[] = "" "VAR" " nx- : INTEGER;" - " p : POINTER TO ARRAY 3 OF INTEGER;" + " p : POINTER TO ARRAY 3 OF RECORD i, j, k : INTEGER END;" + " q : POINTER TO RECORD x, y, z : INTEGER END;" "" "PROCEDURE ChParam(VAR i : INTEGER);" "BEGIN" @@ -20,7 +21,8 @@ static char source_test[] = "" "BEGIN;" " NEW(p);" - " p[0] := 1;" + " p[2].k := 1;" + " NEW(q);" " " " Out.Open;" " ChParam(nx);"