summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: b752043)
raw | patch | inline | side by side (parent: b752043)
author | DeaDDooMER <deaddoomer@deadsoftware.ru> | |
Mon, 24 Jul 2017 19:03:31 +0000 (22:03 +0300) | ||
committer | DeaDDooMER <deaddoomer@deadsoftware.ru> | |
Mon, 24 Jul 2017 19:03:31 +0000 (22:03 +0300) |
generator.c | [new file with mode: 0644] | patch | blob |
generator.h | [new file with mode: 0644] | patch | blob |
make.sh | patch | blob | history | |
oberon.c | patch | blob | history | |
oberon.h | patch | blob | history | |
run.sh | [new file with mode: 0755] | patch | blob |
test.c | patch | blob | history | |
test_gcc_jit/make.sh | [deleted file] | patch | blob | history |
test_gcc_jit/s1 | [deleted file] | patch | blob | history |
test_gcc_jit/s1.c | [deleted file] | patch | blob | history |
diff --git a/generator.c b/generator.c
--- /dev/null
+++ b/generator.c
@@ -0,0 +1,225 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <string.h>
+#include <assert.h>
+
+#include "oberon.h"
+#include "generator.h"
+
+#include <libgccjit.h>
+
+/*
+ * oberon_var_t -> gvar == gcc_jit_lvalue;
+ * oberon_type_t -> gtype == gcc_jit_type;
+ * oberon_context_t -> gctx == gen_context_t;
+ */
+
+typedef struct
+{
+ gcc_jit_context * gcc_context;
+ gcc_jit_block * gcc_block;
+ gcc_jit_result * gcc_result;
+} gen_context_t;
+
+static void printcontext(oberon_context_t * ctx, char * s)
+{
+/*
+ gen_context_t * gen_context = ctx -> gen_context;
+ gcc_jit_context * gcc_context = gen_context -> gcc_context;
+ gcc_jit_block * gcc_block = gen_context -> gcc_block;
+
+ printf("%s:\n", s);
+ printf(" ctx = %p:\n", ctx);
+ printf(" gctx = %p:\n", gctx);
+ printf(" context = %p:\n", context);
+ printf(" block = %p:\n", block);
+*/
+}
+
+// =======================================================================
+// ALLOC
+// =======================================================================
+
+void
+oberon_generator_init_context(oberon_context_t * ctx)
+{
+ gen_context_t * gen_context = malloc(sizeof *gen_context);
+ memset(gen_context, 0, sizeof *gen_context);
+
+ gcc_jit_context * gcc_context;
+ gcc_context = gcc_jit_context_acquire();
+
+ ctx -> gen_context = gen_context;
+ gen_context -> gcc_context = gcc_context;
+
+ printcontext(ctx, "oberon_generator_init_context");
+}
+
+void
+oberon_generator_destroy_context(oberon_context_t * ctx)
+{
+ printcontext(ctx, "oberon_generator_destroy_context");
+
+ gen_context_t * gen_context = ctx -> gen_context;
+ gcc_jit_context * gcc_context = gen_context -> gcc_context;
+
+ gcc_jit_context_release(gcc_context);
+}
+
+void
+oberon_generator_init_type(oberon_context_t * ctx, oberon_type_t * type)
+{
+ printcontext(ctx, "oberon_generator_init_type");
+
+ gen_context_t * gen_context = ctx -> gen_context;
+ gcc_jit_context * gcc_context = gen_context -> gcc_context;
+
+ gcc_jit_type * gen_type;
+ if(type -> class == OBERON_TYPE_INTEGER)
+ {
+ gen_type = gcc_jit_context_get_int_type(gcc_context, type -> size, 1);
+ }
+ else if(type -> class == OBERON_TYPE_BOOLEAN)
+ {
+ gen_type = gcc_jit_context_get_type(gcc_context, GCC_JIT_TYPE_BOOL);
+ }
+ else
+ {
+ oberon_error(ctx, "oberon_generator_init_type: invalid type class %i", type -> class);
+ }
+
+ type -> gen_type = gen_type;
+}
+
+void
+oberon_generator_init_var(oberon_context_t * ctx, oberon_var_t * var)
+{
+ printcontext(ctx, "oberon_generator_init_var");
+
+ gen_context_t * gen_context = ctx -> gen_context;
+ gcc_jit_context * gcc_context = gen_context -> gcc_context;
+ gcc_jit_type * gen_type = var -> type -> gen_type;
+ const char * name = var -> name;
+
+ gcc_jit_lvalue * gen_var;
+ gen_var = gcc_jit_context_new_global(gcc_context, NULL, GCC_JIT_GLOBAL_INTERNAL, gen_type, name);
+
+ var -> gen_var = gen_var;
+}
+
+// =======================================================================
+// GENERATOR
+// =======================================================================
+
+static gcc_jit_rvalue *
+oberon_generate_rvalue_from_item(oberon_context_t * ctx, oberon_item_t * item)
+{
+ printcontext(ctx, "oberon_generate_rvalue_from_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)
+ {
+ 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)
+ {
+ gcc_jit_type * bool_type = gcc_jit_context_get_type(gcc_context, GCC_JIT_TYPE_BOOL);
+ if(item -> boolean)
+ {
+ right = gcc_jit_context_one(gcc_context, bool_type);
+ }
+ else
+ {
+ right = gcc_jit_context_zero(gcc_context, bool_type);
+ }
+ printf("PUSH (bool) %i\n", item -> boolean);
+ }
+ else
+ {
+ oberon_error(ctx, "oberon_generate_push: invalid mode %i", item -> mode);
+ }
+
+ return right;
+}
+
+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;
+}
+
+void
+oberon_generate_assign(oberon_context_t * ctx, oberon_item_t * src, oberon_item_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);
+
+ 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_block_add_assignment(gcc_block, NULL, left, right);
+}
+
+void
+oberon_generate_code(oberon_context_t * ctx)
+{
+ gen_context_t * gen_context = ctx -> gen_context;
+ gcc_jit_context * gcc_context = gen_context -> gcc_context;
+
+ gcc_jit_result * gcc_result;
+ gcc_result = gcc_jit_context_compile(gcc_context);
+
+ gen_context -> gcc_result = gcc_result;
+ ctx -> mod -> begin = gcc_jit_result_get_code(gcc_result, "BEGIN");
+}
diff --git a/generator.h b/generator.h
--- /dev/null
+++ b/generator.h
@@ -0,0 +1,11 @@
+void oberon_generator_init_context(oberon_context_t * ctx);
+void oberon_generator_destroy_context(oberon_context_t * ctx);
+void 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);
+
+void oberon_generate_begin_module(oberon_context_t * ctx);
+void oberon_generate_end_module(oberon_context_t * ctx);
+
+void oberon_generate_assign(oberon_context_t * ctx, oberon_item_t * src, oberon_item_t * dst);
+
+void oberon_generate_code(oberon_context_t * ctx);
index fe43cd6eec9c87e79c7779006915f7aeba8d6932..286e5ff578a2f1b1586217a09e1931abaa63a860 100755 (executable)
--- a/make.sh
+++ b/make.sh
set -e
-cc -g -Wall -Werror -std=c11 *.c
+cc -g -Wall -Werror -std=c11 -lgccjit *.c
diff --git a/oberon.c b/oberon.c
index e411c6c2fdaa455bf15fddcd54c7b94a37f3c8c3..4dfc604a5f38159b0d1668b8376b0cc4fa8195e7 100644 (file)
--- a/oberon.c
+++ b/oberon.c
#include <stdarg.h>
#include <ctype.h>
#include <string.h>
+
#include "oberon.h"
+#include "generator.h"
enum {
EOF_ = 0,
COLON,
BEGIN,
ASSIGN,
- INTEGER
-};
-
-enum {
- MODE_VAR,
- MODE_INTEGER,
+ INTEGER,
+ TRUE,
+ FALSE,
+ LPAREN,
+ RPAREN
};
-typedef struct
-{
- int mode;
- int integer;
- oberon_var_t * var;
-} oberon_item_t;
-
// =======================================================================
// UTILS
// =======================================================================
-static void
+void
oberon_error(oberon_context_t * ctx, const char * fmt, ...)
{
va_list ptr;
{
int class;
- if(item -> mode == MODE_INTEGER)
+ switch(item -> mode)
{
- class = OBERON_TYPE_INTEGER;
- }
- else if(item -> mode == MODE_VAR)
- {
- class = item -> var -> type -> class;
- }
- else
- {
- oberon_error(ctx, "oberon_item_to_type_class: wat");
+ case MODE_INTEGER:
+ class = OBERON_TYPE_INTEGER;
+ break;
+ case MODE_BOOLEAN:
+ class = OBERON_TYPE_BOOLEAN;
+ break;
+ case MODE_VAR:
+ class = item -> var -> type -> class;
+ break;
+ default:
+ oberon_error(ctx, "oberon_item_to_type_class: wat");
+ break;
}
return class;
}
+static void
+oberon_autocast_to(oberon_context_t * ctx, oberon_item_t * from, oberon_item_t * to)
+{
+ int from_class = oberon_item_to_type_class(ctx, from);
+ int to_class = oberon_item_to_type_class(ctx, to);
+
+ if(from_class != to_class)
+ {
+ oberon_error(ctx, "oberon_autocast_to: types not matched %i -> %i", from_class, to_class);
+ }
+}
+
// =======================================================================
// TABLE
// =======================================================================
memset(newvar, 0, sizeof *newvar);
newvar -> name = name;
newvar -> type = type;
+ oberon_generator_init_var(ctx, newvar);
x -> next = newvar;
}
-// =======================================================================
-// GENERATOR
-// =======================================================================
-
-static void
-oberon_generate_assign(oberon_context_t * ctx, void * src, void * dst, int size)
-{
- printf("G: %p := %p (%i);\n", dst, src, size);
-}
-
// =======================================================================
// SCANER
// =======================================================================
c = ctx -> code[i];
}
- char * ident = malloc(len + 2);
+ char * ident = malloc(len + 1);
memcpy(ident, &ctx->code[ctx->code_index], len);
- ident[len + 1] = 0;
+ ident[len] = 0;
ctx -> code_index = i;
ctx -> c = ctx -> code[i];
{
ctx -> token = BEGIN;
}
+ else if(strcmp(ident, "TRUE") == 0)
+ {
+ ctx -> token = TRUE;
+ }
+ else if(strcmp(ident, "FALSE") == 0)
+ {
+ ctx -> token = FALSE;
+ }
}
static void
}
}
+static void
+oberon_read_symbol(oberon_context_t * ctx)
+{
+ int c = ctx -> c;
+ switch(c)
+ {
+ case 0:
+ ctx -> token = EOF_;
+ break;
+ case ';':
+ ctx -> token = SEMICOLON;
+ oberon_get_char(ctx);
+ break;
+ case ':':
+ ctx -> token = COLON;
+ oberon_get_char(ctx);
+ if(ctx -> c == '=')
+ {
+ ctx -> token = ASSIGN;
+ oberon_get_char(ctx);
+ }
+ break;
+ case '.':
+ ctx -> token = DOT;
+ oberon_get_char(ctx);
+ break;
+ case '(':
+ ctx -> token = LPAREN;
+ oberon_get_char(ctx);
+ break;
+ case ')':
+ ctx -> token = RPAREN;
+ oberon_get_char(ctx);
+ break;
+ default:
+ oberon_error(ctx, "invalid char");
+ break;
+ }
+}
+
static void
oberon_read_token(oberon_context_t * ctx)
{
}
else
{
- switch(c)
- {
- case 0: ctx -> token = EOF_; break;
- case ';': ctx -> token = SEMICOLON; oberon_get_char(ctx); break;
- case ':':
- /****************************************************/
- ctx -> token = COLON; oberon_get_char(ctx);
- if(ctx -> c == '=')
- {
- ctx -> token = ASSIGN;
- oberon_get_char(ctx);
- }
- break;
- /****************************************************/
- case '.': ctx -> token = DOT; oberon_get_char(ctx); break;
- default: oberon_error(ctx, "invalid char");
- }
+ oberon_read_symbol(ctx);
}
}
+// =======================================================================
+// EXPR
+// =======================================================================
+
+static void oberon_expect_token(oberon_context_t * ctx, int token);
+static oberon_item_t * oberon_expr(oberon_context_t * ctx);
+static void oberon_assert_token(oberon_context_t * ctx, int token);
+static char * oberon_assert_ident(oberon_context_t * ctx);
+
+static oberon_item_t *
+oberon_factor(oberon_context_t * ctx)
+{
+ char * name;
+ oberon_var_t * var;
+
+ oberon_item_t * item = malloc(sizeof *item);
+ memset(item, 0, sizeof *item);
+
+ switch(ctx -> token)
+ {
+ case IDENT:
+ name = oberon_assert_ident(ctx);
+ var = oberon_find_var(ctx, name);
+ if(var == NULL)
+ {
+ oberon_error(ctx, "undefined variable %s", name);
+ }
+ item -> mode = MODE_VAR;
+ item -> var = var;
+ break;
+ case INTEGER:
+ item -> mode = MODE_INTEGER;
+ item -> integer = ctx -> integer;
+ oberon_assert_token(ctx, INTEGER);
+ break;
+ case TRUE:
+ item -> mode = MODE_BOOLEAN;
+ item -> boolean = 1;
+ oberon_assert_token(ctx, TRUE);
+ break;
+ case FALSE:
+ item -> mode = MODE_BOOLEAN;
+ item -> boolean = 0;
+ oberon_assert_token(ctx, FALSE);
+ break;
+ case LPAREN:
+ oberon_assert_token(ctx, LPAREN);
+ item = oberon_expr(ctx);
+ oberon_assert_token(ctx, RPAREN);
+ break;
+ default:
+ oberon_error(ctx, "invalid expression");
+ }
+
+ return item;
+}
+
+static oberon_item_t *
+oberon_expr(oberon_context_t * ctx)
+{
+ return oberon_factor(ctx);
+}
+
// =======================================================================
// PARSER
// =======================================================================
static char *
oberon_assert_ident(oberon_context_t * ctx)
{
- char * ident;
oberon_expect_token(ctx, IDENT);
- ident = ctx -> string;
+ char * ident = ctx -> string;
oberon_read_token(ctx);
return ident;
}
}
}
-static oberon_item_t *
-oberon_expr(oberon_context_t * ctx)
-{
- oberon_item_t * item = malloc(sizeof *item);
- memset(item, 0, sizeof *item);
-
- if(ctx -> token == IDENT)
- {
- char * name = oberon_assert_ident(ctx);
- oberon_var_t * var = oberon_find_var(ctx, name);
- if(var == NULL)
- {
- oberon_error(ctx, "undefined variable");
- }
- item -> mode = MODE_VAR;
- item -> var = var;
- }
- else if(ctx -> token == INTEGER)
- {
- item -> mode = MODE_INTEGER;
- item -> integer = ctx -> integer;
- oberon_assert_token(ctx, INTEGER);
- }
- else
- {
- oberon_error(ctx, "invalid expression");
- }
-
- return item;
-}
-
static void
oberon_assign(oberon_context_t * ctx, oberon_item_t * src, oberon_item_t * dst)
{
@@ -367,16 +430,9 @@ oberon_assign(oberon_context_t * ctx, oberon_item_t * src, oberon_item_t * dst)
oberon_error(ctx, "invalid assignment");
}
- int src_class = oberon_item_to_type_class(ctx, src);
- int dst_class = oberon_item_to_type_class(ctx, dst);
-
- if(src_class != dst_class)
- {
- oberon_error(ctx, "types not matched");
- }
+ oberon_autocast_to(ctx, src, dst);
- // TODO: code generation
- oberon_generate_assign(ctx, 0, 0, 4);
+ oberon_generate_assign(ctx, src, dst);
}
static void
}
static void
-oberon_parse_it(oberon_context_t * ctx)
+oberon_parse_module(oberon_context_t * ctx)
{
char *name1, *name2;
oberon_read_token(ctx);
if(ctx -> token == BEGIN)
{
oberon_assert_token(ctx, BEGIN);
+ oberon_generate_begin_module(ctx);
oberon_statement_seq(ctx);
+ oberon_generate_end_module(ctx);
}
oberon_assert_token(ctx, END);
oberon_type_t * types = malloc(sizeof *types);
memset(types, 0, sizeof *types);
+ oberon_generator_init_context(ctx);
ctx -> types = types;
return ctx;
}
+void
+oberon_destroy_context(oberon_context_t * ctx)
+{
+ oberon_generator_destroy_context(ctx);
+ free(ctx);
+}
+
oberon_module_t *
oberon_compile_module(oberon_context_t * ctx, const char * code)
{
ctx -> mod -> vars = vars;
oberon_init_scaner(ctx, code);
- oberon_parse_it(ctx);
+ oberon_parse_module(ctx);
+
+ oberon_generate_code(ctx);
return mod;
}
oberon_type_t * newtype = malloc(sizeof *newtype);
memcpy(newtype, type, sizeof *newtype);
newtype -> next = NULL;
+ oberon_generator_init_type(ctx, newtype);
x -> next = newtype;
}
diff --git a/oberon.h b/oberon.h
index 7fee329106ba6f15a64fa07afbeaf1deff994f35..ec742c6bd7af90c18b3850a37fe2163b12407de4 100644 (file)
--- a/oberon.h
+++ b/oberon.h
#ifndef EMBEDED_OBERON_SCRIPT_H
#define EMBEDED_OBERON_SCRIPT_H
-enum {
- OBERON_TYPE_INTEGER,
- OBERON_TYPE_BOOLEAN,
-};
-
typedef struct oberon_var_s oberon_var_t;
typedef struct oberon_type_s oberon_type_t;
typedef struct oberon_module_s oberon_module_t;
typedef struct oberon_context_s oberon_context_t;
+enum {
+ OBERON_TYPE_INTEGER,
+ OBERON_TYPE_BOOLEAN,
+};
+
struct oberon_type_s
{
char * name;
int class;
int size;
oberon_type_t * next;
+
+ void * gen_type;
};
struct oberon_var_s
char * name;
oberon_type_t * type;
oberon_var_t * next;
+
+ void * gen_var;
};
struct oberon_module_s
{
char * name;
oberon_var_t * vars;
+
+ void (* begin)();
};
struct oberon_context_s
int integer;
oberon_module_t * mod;
-
oberon_type_t * types;
+
+ void * gen_context;
+};
+
+enum {
+ MODE_VAR,
+ MODE_INTEGER,
+ MODE_BOOLEAN
};
+typedef struct
+{
+ int mode;
+ int integer;
+ int boolean;
+ oberon_var_t * var;
+} oberon_item_t;
+
oberon_context_t * oberon_create_context();
+void oberon_destroy_context(oberon_context_t * ctx);
void oberon_register_global_type(oberon_context_t * ctx, oberon_type_t * type);
oberon_module_t * oberon_compile_module(oberon_context_t * ctx, const char * code);
+void oberon_error(oberon_context_t * ctx, const char * fmt, ...);
#endif // EMBEDED_OBERON_SCRIPT_H
diff --git a/run.sh b/run.sh
--- /dev/null
+++ b/run.sh
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+set -e
+
+export PATH="/usr/lib/gcc/x86_64-pc-linux-gnu/7.1.1:${PATH}"
+export LIBRARY_PATH="/usr/lib/gcc/x86_64-pc-linux-gnu/7.1.1:${LIBRARY_PATH}"
+
+exec ./a.out
index 2247eac4b7f42e6c463a01918e822d2adf45915e..7149026862087a8f63577916ffd361e8b89b08ef 100644 (file)
--- a/test.c
+++ b/test.c
static const char source[] =
"MODULE Test;"
"VAR"
+ " k : INTEGER;"
" i : INTEGER;"
" b : BOOLEAN;"
"BEGIN"
- " i := 10;"
+ " k := 10;"
+ " i := k;"
+ " b := TRUE;"
"END Test."
;
oberon_register_global_type(ctx, &integer);
oberon_register_global_type(ctx, &boolean);
mod = oberon_compile_module(ctx, source);
+ oberon_destroy_context(ctx);
return 0;
}
diff --git a/test_gcc_jit/make.sh b/test_gcc_jit/make.sh
--- a/test_gcc_jit/make.sh
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/bin/sh
-
-set -e
-
-gcc -g -Wall -Werror -std=c11 -lgccjit s1.c -o s1
diff --git a/test_gcc_jit/s1 b/test_gcc_jit/s1
deleted file mode 100755 (executable)
index 143c368..0000000
Binary files a/test_gcc_jit/s1 and /dev/null differ
index 143c368..0000000
Binary files a/test_gcc_jit/s1 and /dev/null differ
diff --git a/test_gcc_jit/s1.c b/test_gcc_jit/s1.c
--- a/test_gcc_jit/s1.c
+++ /dev/null
@@ -1,22 +0,0 @@
-#include <libgccjit.h>
-
-gcc_jit_context * ctxt;
-
-int
-main(int argc, char **argv)
-{
- ctxt = gcc_jit_context_acquire();
-
- cc_jit_type * void_type = gcc_jit_context_get_type(ctxt, GCC_JIT_TYPE_VOID);
-
- gcc_jit_function * func = gcc_jit_context_new_function(
- ctxt, NULL, GCC_JIT_FUNCTION_EXPORTED, void_type, "BEGIN", 0, NULL, 0
- );
-
- gcc_jit_block * block = gcc_jit_function_new_block (func, NULL);
-
-
-
- gcc_jit_context_release(ctxt);
- return 0;
-}