summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: d1b4e7f)
raw | patch | inline | side by side (parent: d1b4e7f)
author | DeaDDooMER <deaddoomer@deadsoftware.ru> | |
Mon, 24 Jul 2017 20:01:34 +0000 (23:01 +0300) | ||
committer | DeaDDooMER <deaddoomer@deadsoftware.ru> | |
Mon, 24 Jul 2017 20:01:34 +0000 (23:01 +0300) |
generator.c | patch | blob | history | |
make.sh | patch | blob | history | |
notes | patch | blob | history | |
oberon.c | patch | blob | history | |
oberon.h | patch | blob | history | |
test.c | patch | blob | history |
diff --git a/generator.c b/generator.c
index bad063d57adcac9ee2c45d5f1442febdf5839055..94bc1696a8f54f281e8868cfa02d7a51f1800cb0 100644 (file)
--- a/generator.c
+++ b/generator.c
#include <string.h>
#include <assert.h>
+#include <gc.h>
+
#include "oberon.h"
#include "generator.h"
+// =======================================================================
+// INTERNAL FUNCTIONS
+// =======================================================================
+
+static void *
+__OBERON_ALLOC__ (size_t bytes)
+{
+ void * p = GC_MALLOC(bytes);
+ memset(p, 0, bytes);
+ return p;
+}
+
// =======================================================================
// ALLOC
// =======================================================================
ctx -> gen_context = gen_context;
gen_context -> gcc_context = gcc_context;
+
+ gcc_jit_type * void_ptr_type = gcc_jit_context_get_type(gcc_context, GCC_JIT_TYPE_VOID_PTR);
+ gcc_jit_type * size_type = gcc_jit_context_get_type(gcc_context, GCC_JIT_TYPE_SIZE_T);
+ gcc_jit_type * alloc_ptr_type = gcc_jit_context_new_function_ptr_type(
+ gcc_context, NULL, void_ptr_type, 1, &size_type, 0
+ );
+ gen_context -> gcc_alloc = gcc_jit_context_new_global(
+ gcc_context, NULL, GCC_JIT_GLOBAL_EXPORTED, alloc_ptr_type, "__OBERON_ALLOC__"
+ );
}
void
static gcc_jit_rvalue * 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);
+static int
+oberon_generator_get_type_size(oberon_type_t * type)
+{
+ printf("TODO: oberon_generator_get_type_size\n");
+ return 128;
+}
+
void
oberon_generate_begin_module(oberon_context_t * ctx)
{
}
else
{
- oberon_error(ctx, "invalid lvalue expression");
+ oberon_error(ctx, "lvalue_from_item: invalid mode %i", item -> mode);
}
return left;
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)
+ {
+ int type_size = oberon_generator_get_type_size(item -> type);
+ int array_size = type_size;
+
+ int num = item -> num_args;
+ oberon_expr_t * arg = item -> args;
+ for(int i = 0; i < num; i++)
+ {
+ array_size *= arg -> item.integer;
+ arg = arg -> next;
+ }
+
+ gcc_jit_type * size_type;
+ size_type = gcc_jit_context_get_type(gcc_context, GCC_JIT_TYPE_SIZE_T);
+
+ gcc_jit_rvalue * fnarg;
+ fnarg = gcc_jit_context_new_rvalue_from_int(gcc_context, size_type, array_size);
+
+ gcc_jit_type * result_type = item -> result -> gen_type -> gcc_type;
+ gcc_jit_rvalue * gcc_alloc = gcc_jit_lvalue_as_rvalue(gen_context -> gcc_alloc);
+ right = gcc_jit_context_new_call_through_ptr(gcc_context, NULL, gcc_alloc, 1, &fnarg);
+ right = gcc_jit_context_new_cast(gcc_context, NULL, right, result_type);
+ }
else
{
oberon_error(ctx, "rvalue_from_item: invalid mode %i", item -> mode);
gen_context -> gcc_result = gcc_result;
+ typedef void * (*TOberonAlloc)(size_t);
+ TOberonAlloc * fn_alloc_ptr = gcc_jit_result_get_global(gcc_result, "__OBERON_ALLOC__");
+ *fn_alloc_ptr = __OBERON_ALLOC__;
+
// ctx -> mod -> begin = gcc_jit_result_get_code(gcc_result, "BEGIN");
}
index 286e5ff578a2f1b1586217a09e1931abaa63a860..1f95bcf593d5824856bf83e51bd355a2315c2a85 100755 (executable)
--- a/make.sh
+++ b/make.sh
set -e
-cc -g -Wall -Werror -std=c11 -lgccjit *.c
+cc -g -Wall -Werror -std=c11 -lgccjit -lgc *.c
index fbb1be93c7374f5bc8a2f590932f0706c3640d5f..977d7cd3e9966f7e5280050849215b3eae712114 100644 (file)
--- a/notes
+++ b/notes
-- нету процедуры NEW
+- размеры типов не вычисляются (oberon_generator_get_type_size)
+ в libgccjit нет средств получения размера типов, в т.ч. структур
+ Придётся гадать.
+- процедура NEW создаёт массивы только статической размерности (и не создаёт структуры).
- нету открытых массивов
- нету операторов if, while и т.д.
- не реализована свёртка констант
- не протестированы типы разнных размеров
-- не реализовано присваивание к переменным-процедурам:
+- не Ñ\80еализовано пÑ\80иÑ\81ваивание пÑ\80оÑ\86едÑ\83Ñ\80 к пеÑ\80еменнÑ\8bм-пÑ\80оÑ\86едÑ\83Ñ\80ам:
в libgccjit нет средств получения указателя на функцию.
Как решение-костыль - получение указателя в основной программе и сохранение в переменной.
- не реализовано расширение типа record:
diff --git a/oberon.c b/oberon.c
index e857b1d1ec6f93e454b5439cdcf81f96c150d167..931d948c57bc15c0faf906e0a6f23b52f991a122 100644 (file)
--- a/oberon.c
+++ b/oberon.c
@@ -665,7 +665,13 @@ oberon_autocast_to(oberon_context_t * ctx, oberon_expr_t * expr, oberon_type_t *
{
if(pref -> class != expr -> result -> class)
{
- oberon_error(ctx, "incompatible types");
+ if(pref -> class != OBERON_TYPE_PROCEDURE)
+ {
+ if(expr -> result -> class != OBERON_TYPE_POINTER)
+ {
+ oberon_error(ctx, "incompatible types");
+ }
+ }
}
if(pref -> class == OBERON_TYPE_INTEGER)
{
if(param -> class == OBERON_CLASS_VAR_PARAM)
{
- if(arg -> is_item)
+ if(arg -> read_only)
{
- switch(arg -> item.mode)
- {
- case MODE_VAR:
- case MODE_INDEX:
- case MODE_FIELD:
- // Допустимо разыменование?
- //case MODE_DEREF:
- break;
- default:
- oberon_error(ctx, "var-parameter accept only variables");
- break;
- }
+ oberon_error(ctx, "assign to read-only var");
}
+
+ //if(arg -> is_item)
+ //{
+ // switch(arg -> item.mode)
+ // {
+ // case MODE_VAR:
+ // case MODE_INDEX:
+ // case MODE_FIELD:
+ // // Допустимо разыменование?
+ // //case MODE_DEREF:
+ // break;
+ // default:
+ // oberon_error(ctx, "var-parameter accept only variables");
+ // break;
+ // }
+ //}
}
oberon_autocast_to(ctx, arg, param -> type);
arg = arg -> next;
@@ -2564,6 +2575,69 @@ oberon_make_abs_call(oberon_context_t * ctx, int num_args, oberon_expr_t * list_
return expr;
}
+static void
+oberon_make_new_call(oberon_context_t * ctx, int num_args, oberon_expr_t * list_args)
+{
+ if(num_args < 1)
+ {
+ oberon_error(ctx, "too few arguments");
+ }
+
+ if(num_args > 1)
+ {
+ oberon_error(ctx, "too mach arguments");
+ }
+
+ oberon_expr_t * dst;
+ dst = list_args;
+
+ oberon_type_t * type;
+ type = dst -> result;
+
+ if(type -> class != OBERON_TYPE_POINTER)
+ {
+ oberon_error(ctx, "not a pointer");
+ }
+
+ type = type -> base;
+
+ oberon_expr_t * src;
+ 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)
+ {
+ oberon_expr_t * size;
+ size = last_size = oberon_new_item(MODE_INTEGER, ctx -> int_type, 1);
+ size -> item.integer = base -> size;
+
+ last_size -> next = size;
+ last_size = size;
+ 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;
+ }
+ else
+ {
+ oberon_error(ctx, "oberon_make_new_call: wat");
+ }
+
+ oberon_assign(ctx, src, dst);
+}
+
oberon_context_t *
oberon_create_context(ModuleImportCallback import_module)
{
register_default_types(ctx);
oberon_new_intrinsic(ctx, "ABS", oberon_make_abs_call, NULL);
+ oberon_new_intrinsic(ctx, "NEW", NULL, oberon_make_new_call);
return ctx;
}
diff --git a/oberon.h b/oberon.h
index ef9ad7f1c891223eb2241ef8d4020e3855a50645..4b785453befda47bbdcfe1ccf9c7b9a67ccfd1cc 100644 (file)
--- a/oberon.h
+++ b/oberon.h
gcc_jit_result * gcc_result;
gen_block_t * block;
unsigned record_count;
+ gcc_jit_lvalue * gcc_alloc;
};
typedef struct oberon_type_s oberon_type_t;
MODE_INDEX,
MODE_FIELD,
MODE_DEREF,
- MODE_NIL
+ MODE_NIL,
+ MODE_NEWARR
};
enum
int num_args;
oberon_expr_t * args;
+ oberon_type_t * type;
};
struct oberon_oper_s
index c3a4b1467f51256bbec89e210374cb69d90a44d8..fc0033339d03fff36dbd6f52ba6989c3df777c0c 100644 (file)
--- a/test.c
+++ b/test.c
"(* Main module *)"
"MODULE Test;"
"IMPORT Out;"
+ ""
+ "VAR"
+ " nx- : INTEGER;"
+ " p : POINTER TO ARRAY 3 OF INTEGER;"
+ ""
+ "PROCEDURE ChParam(VAR i : INTEGER);"
+ "BEGIN"
+ " i := 1234;"
+ "END ChParam;"
+ ""
"BEGIN;"
+ " NEW(p);"
+ " p[0] := 1;"
+ " "
" Out.Open;"
- " Out.Int(666, 0);"
+ " ChParam(nx);"
+ " Out.Int(nx, 0);"
" Out.Ln;"
"END Test."
;
static char source_out[] =
"MODULE Out;"
+ "(* Interface to outer program ;) *)"
"VAR"
" Open- : PROCEDURE;"
// " Char- : PROCEDURE(ch : CHAR);"
static TOutInt * OutIntPtr;
void ImplOutInt(int i, int n)
{
- printf("%i", i);
+ char number[22];
+ snprintf(number, 22, "%i", i);
+ int len = strlen(number);
+ for(int i = 0; i < n - len; i++)
+ {
+ putchar(' ');
+ }
+ printf("%s", number);
}
typedef void (*TOutLn)();
static TOutLn * OutLnPtr;
void ImplOutLn()
{
- printf("\n");
+ putchar('\n');
}
void init_system_modules()