fucked shit up

This commit is contained in:
anon 2024-07-22 18:35:21 +02:00
parent 4cbec3ec8a
commit b0a54971b3
11 changed files with 390 additions and 238 deletions

View File

@ -76,8 +76,8 @@ ${OBJECT.d}/%.pluglock: ${OBJECT.d}/%.pp
touch $@ touch $@
test: ${OUT} test: ${OUT}
ORIGIN="$$(realpath .)" PATH="$$(realpath .):${PATH}" cmdtest -ORIGIN="$$(realpath .)" PATH="$$(realpath .):${PATH}" cmdtest
${WRAP} ./${OUT} test/nop.eax -${WRAP} ./${OUT} test/nop.eax
bootstrap: bootstrap:
./library/bootstrap.sh ./library/bootstrap.sh

View File

@ -1,4 +1,5 @@
#ifndef ASSEMBLER_H #ifndef ASSEMBLER_H
#define ASSEMBLER_H
enum { enum {
D8, // 8-bit D8, // 8-bit
@ -183,5 +184,4 @@ extern int was_instruction_array_empty;
extern void assemble (unsigned int count, unsigned int * array); extern void assemble (unsigned int count, unsigned int * array);
#define ASSEMBLER_H
#endif #endif

View File

@ -32,7 +32,7 @@ int compile_deinit(void) {
static static
void dump_variable_to_assembler(void * data) { void dump_variable_to_assembler(void * data) {
symbol_t * variable = (symbol_t*)data; symbol_t * variable = (symbol_t*)data;
if (variable->symbol_type != VARIABLE) { if (variable->symbol_type != VARIABLE_SYMBOL) {
return; return;
} }

View File

@ -6,12 +6,14 @@
#include <stdarg.h> #include <stdarg.h>
#include "eaxhla.h" #include "eaxhla.h"
__attribute__((unused))
static static
void breakpoint(void) { ; } void breakpoint(void) { ; }
# define debug_puts(msg) do { puts(msg); } while (0) # define debug_puts(msg) do { puts(msg); } while (0)
static // this is less horid than macro varargs __attribute__((unused))
static
void debug_printf(const char * const fmt, ...) { void debug_printf(const char * const fmt, ...) {
va_list args; va_list args;
va_start(args, fmt); va_start(args, fmt);
@ -19,19 +21,22 @@ void debug_printf(const char * const fmt, ...) {
va_end(args); va_end(args);
} }
__attribute__((unused))
static static
void dump_variable(void * data) { void dump_variable(void * data) {
symbol_t * variable = (symbol_t*)data; symbol_t * variable = (symbol_t*)data;
if (variable->symbol_type != VARIABLE) { return; } if (variable->symbol_type != VARIABLE_SYMBOL) { return; }
if (variable->elements == 1) { if (variable->elements == 1) {
printf("{ .name = '%s', .value = '%ld' }\n", printf("{ .name = '%s', .id = %d, .value = '%ld' }\n",
variable->name, variable->name,
variable->_id,
variable->value variable->value
); );
} else { } else {
printf("{ .name = '%s', .elements = '%llu', .array_value = \"%.*s\" }\n", printf("{ .name = '%s', .id = %d, .elements = '%lu', .array_value = \"%.*s\" }\n",
variable->name, variable->name,
variable->_id,
variable->elements, variable->elements,
(int)variable->elements, (int)variable->elements,
(char*)variable->array_value (char*)variable->array_value
@ -39,28 +44,33 @@ void dump_variable(void * data) {
} }
} }
__attribute__((unused))
static static
void debug_dump_variables(void) { void debug_dump_variables(void) {
puts("# Variables:"); puts("# Variables:");
tommy_hashtable_foreach(&symbol_table, dump_variable); tommy_hashtable_foreach(&symbol_table, dump_variable);
} }
__attribute__((unused))
static static
void dump_function(void * data) { void dump_function(void * data) {
symbol_t * function = (symbol_t*)data; symbol_t * function = (symbol_t*)data;
if (function->symbol_type != FUNCTION) { return; } if (function->symbol_type != LABEL_SYMBOL) { return; }
printf("{ .name = '%s' }\n", printf("{ .name = '%s', .id = %d }\n",
function->name function->name,
function->_id
); );
} }
__attribute__((unused))
static static
void debug_dump_functions(void) { void debug_dump_functions(void) {
puts("# Functions:"); puts("# Functions:");
tommy_hashtable_foreach(&symbol_table, dump_function); tommy_hashtable_foreach(&symbol_table, dump_function);
} }
__attribute__((unused))
static static
void debug_dump_symbols(void) { void debug_dump_symbols(void) {
debug_dump_variables(); debug_dump_variables();
@ -68,6 +78,7 @@ void debug_dump_symbols(void) {
printf("# Total variable size: '%d'\n", variable_size_sum()); printf("# Total variable size: '%d'\n", variable_size_sum());
} }
__attribute__((unused))
static static
void debug_token_dump(void) { void debug_token_dump(void) {
extern unsigned int * token_array; extern unsigned int * token_array;

View File

@ -9,6 +9,7 @@
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdbool.h>
#include "eaxhla.tab.h" #include "eaxhla.tab.h"
@ -16,7 +17,14 @@
#include "assembler.h" #include "assembler.h"
#include "compile.h" #include "compile.h"
unsigned long long anon_variable_counter = 0; /* Used for naming variables constructed from literals
*/
size_t anon_variable_counter = 0;
/* Used to check whether all labels without
* previous declarations (forward jumps)
* have been declared later in code
*/
size_t unresolved_label_counter = 0;
static unsigned symbol_id = 1; static unsigned symbol_id = 1;
tommy_hashtable symbol_table; tommy_hashtable symbol_table;
@ -38,6 +46,15 @@ int eaxhla_init(void) {
return 0; return 0;
} }
symbol_t * new_symbol(const char * const name) {
symbol_t * r;
r = (symbol_t *)calloc(sizeof(symbol_t), 1);
r->name = strdup(name);
return r;
}
static static
void free_symbol(void * data) { void free_symbol(void * data) {
symbol_t * variable = (symbol_t*)data; symbol_t * variable = (symbol_t*)data;
@ -46,96 +63,19 @@ void free_symbol(void * data) {
} }
int eaxhla_deinit(void) { int eaxhla_deinit(void) {
empty_out_scope();
tommy_hashtable_foreach(&symbol_table, free_symbol); tommy_hashtable_foreach(&symbol_table, free_symbol);
tommy_hashtable_done(&symbol_table); tommy_hashtable_done(&symbol_table);
return 0; return 0;
} }
static
int table_compare_unsigned(const void * arg, const void * obj) {
return *(const unsigned *) arg != ((const symbol_t*)obj)->_hash;
}
static
void * symbol_lookup(const char * const name) {
unsigned lookup_hash = tommy_strhash_u32(0, name);
void * r = tommy_hashtable_search(&symbol_table,
table_compare_unsigned,
&lookup_hash,
lookup_hash
);
return r;
}
static
void symbol_insert(symbol_t * symbol) {
symbol->_hash = tommy_strhash_u32(0, symbol->name);
tommy_hashtable_insert(&symbol_table,
&symbol->_node,
symbol,
symbol->_hash
);
}
void add_program(const char * const name) {
if (is_program_found) {
issue_error("only 1 entry point is allowed and a program block was already found");
}
is_program_found = 1;
append_instructions(ASMDIRMEM, 0);
scope = strdup(name);
}
void add_variable(symbol_t variable) {
if (get_variable(variable.name)) {
issue_error("symbol '%s' redeclared as new variable", variable.name);
return;
}
variable._id = symbol_id++;
variable.symbol_type = VARIABLE;
symbol_t * heap_variable = malloc(sizeof(variable));
memcpy(heap_variable, &variable, sizeof(variable));
symbol_insert(heap_variable);
}
void add_procedure(symbol_t procedure) {
if (get_symbol(procedure.name)) {
issue_error("symbol '%s' redeclared as new function", procedure.name);
return;
}
procedure._id = symbol_id++;
procedure.symbol_type = FUNCTION;
symbol_t * heap_procedure = malloc(sizeof(procedure));
memcpy(heap_procedure, &procedure, sizeof(procedure));
symbol_insert(heap_procedure);
//
append_instructions(ASMDIRMEM, procedure._id);
}
void add_fastcall(const char * const destination) {
symbol_t * function = get_function(destination);
if (!function) {
issue_error("can't fastcall '%s', no such known symbol", destination);
return;
}
append_instructions(CALL, REL, function->_id);
}
/* Are these literals ugly? yes. /* Are these literals ugly? yes.
* However it would be much more painful to calculate the values inline. * However it would be much more painful to calculate the values inline.
*/ */
int can_fit(const int type, const long long value) { int can_fit(const int type, const long long value) {
unsigned long long max = 0; size_t max = 0;
long long min = 0; long long min = 0;
switch (type) { switch (type) {
case U8: { case U8: {
@ -167,9 +107,216 @@ int can_fit(const int type, const long long value) {
max = 4294967295; max = 4294967295;
} break; } break;
} }
return value > 0 ? (unsigned long long)value <= max : value >= min; return value > 0 ? (size_t)value <= max : value >= min;
} }
int validate_array_size(const int size) {
if (size < 1) {
issue_error("cannot create an array of size '%d', because its less than 1", size);
return 1;
}
return 0;
}
static
int table_compare_unsigned(const void * arg, const void * obj) {
return *(const unsigned *) arg != ((const symbol_t*)obj)->_hash;
}
static
void * symbol_lookup(const char * const name) {
unsigned lookup_hash = tommy_strhash_u32(0, name);
void * r = tommy_hashtable_search(&symbol_table,
table_compare_unsigned,
&lookup_hash,
lookup_hash
);
return r;
}
static
void symbol_insert(symbol_t * symbol) {
symbol->_hash = tommy_strhash_u32(0, symbol->name);
tommy_hashtable_insert(&symbol_table,
&symbol->_node,
symbol,
symbol->_hash
);
}
void add_scope(const char * const name){
free(scope);
scope = strdup(name);
}
// XXX: alternative version on the stack
static
char * make_scoped_name(const char * const scope, const char * const name) {
if (!scope) {
return (char*)name;
}
char * r;
const long scl = strlen(scope);
const long nml = strlen(name);
r = malloc(2 + scl + 1 + nml + 1);
r[0] = '_';
r[1] = '_';
memcpy(r + 2, scope, scl);
r[2 + scl] = '_';
memcpy(r + 2 + scl + 1, name, nml);
r[2 + scl + 1 + nml] = '\0';
return r;
}
symbol_t * get_symbol(const char * const name) {
symbol_t * r;
r = symbol_lookup(name);
if (r) {
return r;
}
char * alternative_name = make_scoped_name(scope, name);
r = symbol_lookup(alternative_name);
free(alternative_name);
return r;
}
void add_program(const char * const name) {
(void)name;
if (is_program_found) {
issue_error("only 1 entry point is allowed and a program block was already found");
}
is_program_found = 1;
append_instructions(ASMDIRMEM, 0);
}
static
void _add_variable(unsigned type, const char * const name, size_t size, void * value) {
char * full_name = make_scoped_name(scope, name);
if (get_variable(full_name)) {
issue_error("symbol '%s' redeclared as new variable", full_name);
return;
}
symbol_t * variable = new_symbol(full_name);
variable->elements = size;
variable->type = type;
if (size == 1) {
variable->value = (long)value;
if (!can_fit(type, variable->value)) {
issue_warning("the value \033[1m'%lld'\033[0m will overflow in assignement",
variable->value
);
}
} else {
variable->array_value = value;
validate_array_size(size);
}
variable->_id = symbol_id++;
variable->symbol_type = VARIABLE_SYMBOL;
symbol_insert(variable);
}
void add_variable(unsigned type, const char * const name) {
_add_variable(type, name, 1, 0);
}
void add_variable_with_value(unsigned type, const char * const name, size_t value) {
_add_variable(type, name, 1, (void *)value);
}
void add_array_variable(unsigned type, const char * const name, size_t size) {
_add_variable(type, name, size, 0);
}
void add_array_variable_with_value(unsigned type, const char * const name, size_t size, void * value, size_t value_size) {
if (size < value_size) {
issue_warning("declared array size is smaller than assigned literal, this will cause truncation");
}
_add_variable(type, name, size, value);
}
void add_procedure(const char * const name) {
if (get_symbol(name)) {
issue_error("symbol '%s' redeclared as new function", name);
return;
}
symbol_t * procedure = new_symbol(name);
procedure->_id = symbol_id++;
procedure->symbol_type = LABEL_SYMBOL;
procedure->is_resolved = true;
symbol_insert(procedure);
append_instructions(ASMDIRMEM, procedure->_id);
}
void add_literal(void * data, size_t size) {
char * name;
int ignore = asprintf(&name, "_anon_%lu", anon_variable_counter++);
(void)ignore;
symbol_t * literal = (symbol_t *)calloc(sizeof(symbol_t), 1);
literal->name = name;
literal->elements = size;
literal->array_value = data;
}
static
symbol_t * _add_label(const char * const name, int is_resolved) {
char * full_name = make_scoped_name(scope, name);
symbol_t * label = get_symbol(full_name);
if (label) {
if (label->is_resolved) {
issue_error("symbol '%s' redeclared as new label", name);
} else {
label->is_resolved = true;
--unresolved_label_counter;
}
return label;
}
label = new_symbol(full_name);
label->_id = symbol_id++;
label->symbol_type = LABEL_SYMBOL;
label->is_resolved = is_resolved;
if (!is_resolved) {
++unresolved_label_counter;
}
symbol_insert(label);
return label;
}
void add_label(const char * const name, int is_resolved) {
_add_label(name, is_resolved);
}
void add_fastcall(const char * const destination) {
symbol_t * function = get_symbol(destination);
if (!function) {
issue_error("can't fastcall '%s', no such known symbol", destination);
return;
}
append_instructions(CALL, REL, function->_id);
}
int type2size(const int type) { int type2size(const int type) {
switch (type) { switch (type) {
case U8: case U8:
@ -205,7 +352,7 @@ int size2bytes(const int size) {
static static
void _variable_size_sum_iteration(void * i, void * data) { void _variable_size_sum_iteration(void * i, void * data) {
symbol_t * variable = (symbol_t*)data; symbol_t * variable = (symbol_t*)data;
if (variable->symbol_type != VARIABLE) { return; } if (variable->symbol_type != VARIABLE_SYMBOL) { return; }
int * sum = i; int * sum = i;
@ -218,54 +365,13 @@ int variable_size_sum(void) {
return r; return r;
} }
int validate_array_size(const int size) {
if (size < 1) {
issue_error("cannot create an array of size '%d', because its less than 1", size);
return 1;
}
return 0;
}
char * make_scoped_name(const char * const scope, const char * const name) {
if (!scope) {
return (char*)name;
}
char * r;
const long scl = strlen(scope);
const long nml = strlen(name);
r = malloc(2 + scl + 1 + nml + 1);
r[0] = '_';
r[1] = '_';
memcpy(r + 2, scope, scl);
r[2 + scl] = '_';
memcpy(r + 2 + scl + 1, name, nml);
r[2 + scl + 1 + nml] = '\0';
return r;
}
symbol_t * get_symbol(const char * const name) {
symbol_t * r;
r = symbol_lookup(name);
if (r) {
return r;
}
char * alternative_name = make_scoped_name(scope, name);
r = symbol_lookup(alternative_name);
free(alternative_name);
return r;
}
symbol_t * get_variable(const char * const name) { symbol_t * get_variable(const char * const name) {
symbol_t * r; symbol_t * r;
char * varname = make_scoped_name(scope, name); char * varname = make_scoped_name(scope, name);
r = symbol_lookup(varname); r = symbol_lookup(varname);
if (r if (r
&& r->symbol_type != VARIABLE) { && r->symbol_type != VARIABLE_SYMBOL) {
issue_error("the symbol '%s' is not a variable", name); issue_error("the symbol '%s' is not a variable", name);
return NULL; return NULL;
} }
@ -276,13 +382,46 @@ symbol_t * get_function(const char * const name) {
symbol_t * r; symbol_t * r;
r = symbol_lookup(name); r = symbol_lookup(name);
if (r if (r
&& r->symbol_type != FUNCTION) { && r->symbol_type != LABEL_SYMBOL) {
issue_error("the symbol '%s' is not a function", name); issue_error("the symbol '%s' is not a function", name);
return NULL; return NULL;
} }
return r; return r;
} }
symbol_t * get_relative(const char * const name) {
symbol_t * r;
r = get_symbol(name);
if (r) {
return r;
}
r = _add_label(name, false);
return r;
}
void fin_procedure(void) {
append_instructions(RETN);
}
static
void unresolved_check(void * data) {
symbol_t * label = (symbol_t*)data;
if (label->type != LABEL_SYMBOL) {
return;
}
if (!label->is_resolved) {
issue_error("the label '%s' was never resolved.", label->name);
}
}
void fin_hla(void) {
if (anon_variable_counter) {
tommy_hashtable_foreach(&symbol_table, unresolved_check);
}
}
void issue_warning(const char * const format, ...) { void issue_warning(const char * const format, ...) {
extern char * yyfilename; extern char * yyfilename;

View File

@ -1,27 +1,29 @@
#ifndef EAXHLA_H #ifndef EAXHLA_H
#define EAXHLA_H
#include <tommyds/tommyds/tommyhashtbl.h> #include <tommyds/tommyds/tommyhashtbl.h>
#define WORD_SIZE_IN_BYTES (64/8) #define WORD_SIZE_IN_BYTES (64/8)
// XXX these should be private
typedef enum { typedef enum {
VARIABLE, VARIABLE_SYMBOL,
FUNCTION, LABEL_SYMBOL,
} symbol_type_t; } symbol_type_t;
typedef struct { typedef struct {
symbol_type_t symbol_type; symbol_type_t symbol_type;
union { union {
struct { // VARIABLE struct { // VARIABLE_SYMBOL
int type; int type;
unsigned long long elements; size_t elements;
union { union {
long value; long value;
void * array_value; void * array_value;
}; };
}; };
struct { // FUNCTION struct { // LABEL_SYMBOL
void * unused; int is_resolved;
}; };
}; };
char * name; char * name;
@ -30,10 +32,12 @@ typedef struct {
tommy_node _node; tommy_node _node;
} symbol_t; } symbol_t;
extern tommy_hashtable symbol_table; symbol_t * new_symbol(const char * const name);
/* private:
void free_symbol(void * name);
*/
// Used for naming variables constructed from literals extern tommy_hashtable symbol_table;
extern unsigned long long anon_variable_counter;
typedef struct { typedef struct {
unsigned number : 6; unsigned number : 6;
@ -42,39 +46,54 @@ typedef struct {
extern int system_type; extern int system_type;
/* Used for error discovery
*/
extern int is_program_found; extern int is_program_found;
extern int has_encountered_error; extern int has_encountered_error;
extern char * scope; /* Used for error reporting
extern void empty_out_scope(void); */
// Used for error reporting
extern char * yyfilename; extern char * yyfilename;
extern int eaxhla_init(void); extern int eaxhla_init(void);
extern int eaxhla_deinit(void); extern int eaxhla_deinit(void);
extern char * make_scoped_name(const char * const scope, const char * const name);
extern int can_fit(const int type, const long long value);
extern int validate_array_size(const int size);
extern void add_variable(symbol_t variable);
extern symbol_t * get_variable(const char * const name);
extern symbol_t * get_symbol(const char * const name);
//extern void add_function(symbol_t function);
extern void add_procedure(symbol_t procedure);
extern symbol_t * get_function(const char * const name);
extern void add_program(const char * const name);
extern void add_fastcall(const char * const destination);
extern int type2size(int type);
extern int size2bytes(const int size);
extern int variable_size_sum(void); extern int variable_size_sum(void);
// Language constructs
extern void add_program(const char * const name);
extern void add_scope(const char * const name);
extern void add_variable(unsigned type, const char * const name);
extern void add_variable_with_value(unsigned type, const char * const name, size_t value);
extern void add_array_variable(unsigned type, const char * const name, size_t size);
extern void add_array_variable_with_value(unsigned type, const char * const name, size_t size, void * value, size_t value_size);
extern void add_literal(void * data, size_t size);
extern void add_label(const char * const name, int is_resolved);
extern void add_procedure(const char * const name);
extern void add_fastcall(const char * const destination);
extern void fin_procedure(void);
extern void fin_hla(void);
/* Not implemented
extern symbol_t * add_function(symbol_t function);
extern symbol_t * get_function(const char * const name);
*/
// Asm value constructs
/* These functions MUST return a valid symbol_t or
* we segv and catch fire.
* Unresolved symbol errors are handled internally.
*/
extern symbol_t * get_relative(const char * const name);
extern symbol_t * get_variable(const char * const name);
// XXX: move to assembler.h,
// delete the switch bullshit, you can get away with artimetrics,
// also typedef the D\d+ type
extern int type2size(int type); // XXX: the return type is an anon enum
extern int size2bytes(const int size); // XXX: size is an anon enum
// Error reporting
extern void issue_warning(const char * format, ...); extern void issue_warning(const char * format, ...);
extern void issue_error(const char * format, ...); extern void issue_error(const char * format, ...);
#define EAXHLA_H
#endif #endif

View File

@ -1,6 +1,7 @@
%{ %{
#include <stdlib.h> #include <stdlib.h>
#include "sds/sds.h" #include "sds/sds.h"
#include "eaxhla.h"
#include "eaxhla.tab.h" #include "eaxhla.tab.h"
sds string_literal_buffer; sds string_literal_buffer;
@ -253,13 +254,13 @@ library { BEGIN INITIAL; return END_LIBRARY; }
<IN_COMMENT>{ <IN_COMMENT>{
\n { BEGIN INITIAL; } \n { BEGIN INITIAL; }
.* { ; } .* { ; }
<<EOF>> { yytext = strdup("<EOF>"); issue_error("unterminated comment"); yyterminate(); } <<EOF>> { issue_error("unterminated comment"); yyterminate(); }
} }
<IN_MULTILINE_COMMENT>{ <IN_MULTILINE_COMMENT>{
\*\/ { BEGIN INITIAL; } \*\/ { BEGIN INITIAL; }
.|\n { ; } .|\n { ; }
<<EOF>> { yytext = strdup("<EOF>"); issue_error("unterminated comment"); yyterminate(); } <<EOF>> { issue_error("unterminated comment"); yyterminate(); }
} }
<INITIAL,IN_ARTIMETRIC_BLOCK>{ <INITIAL,IN_ARTIMETRIC_BLOCK>{
@ -285,7 +286,7 @@ library { BEGIN INITIAL; return END_LIBRARY; }
} }
<IN_ARTIMETRIC_BLOCK>{ <IN_ARTIMETRIC_BLOCK>{
<<EOF>> { yytext = strdup("<EOF>"); issue_error("unterminated artimetric block"); yyterminate(); } <<EOF>> { issue_error("unterminated artimetric block"); yyterminate(); }
} }
{identifier} { yylval.strval = strdup(yytext); return IDENTIFIER; } {identifier} { yylval.strval = strdup(yytext); return IDENTIFIER; }

View File

@ -1,14 +1,21 @@
/* EAXHLA parser
* This source file has minimal knowledge about highlevel constructs.
* The only time it interacts with the assembler interface directly is when
* instructions are encountered or processing a machine code block,
* everything else is delegated to eaxhla.c
*/
%code requires { %code requires {
#include "eaxhla.h" #include "eaxhla.h"
} }
%{ %{
#include <stdio.h> #include <stdio.h>
#include <math.h> #include <math.h>
#include <stdbool.h>
#include "eaxhla.h"
#include "eaxhla.yy.h" #include "eaxhla.yy.h"
#include "assembler.h" #include "assembler.h"
#include "compile.h" #include "compile.h"
#include "eaxhla.h"
#include "debug.h" #include "debug.h"
extern void yyfree_leftovers(void); extern void yyfree_leftovers(void);
@ -70,7 +77,7 @@
%token U8 U16 U32 U64 %token U8 U16 U32 U64
%type<intval> type %type<intval> type
%type<varval> declaration %type<varval> declaration
%type<varval> anon_variable %type<varval> stored_literal
// Registers // Registers
%type<regval> register register64s register32s register16s register8s %type<regval> register register64s register32s register16s register8s
@ -94,6 +101,9 @@
%token EXIT BREAK %token EXIT BREAK
%% %%
document: hla { fin_hla(); }
;
hla: %empty hla: %empty
// | library hla // | library hla
| declaration hla // tmp | declaration hla // tmp
@ -102,11 +112,11 @@ hla: %empty
; ;
program: program_head declaration_section MYBEGIN code END_PROGRAM { program: program_head declaration_section MYBEGIN code END_PROGRAM {
empty_out_scope();
} }
; ;
program_head: program_specifier PROGRAM IDENTIFIER { program_head: program_specifier PROGRAM IDENTIFIER {
add_scope($3);
add_program($3); add_program($3);
free($3); free($3);
}; };
@ -121,17 +131,14 @@ system_specifier: UNIX { system_type = UNIX; }
// XXX: end procedure thing // XXX: end procedure thing
function: function_head declaration_section MYBEGIN code END_PROCEDURE { function: function_head declaration_section MYBEGIN code END_PROCEDURE {
append_instructions(RETN); fin_procedure();
empty_out_scope();
} }
; ;
function_head: function_specifier PROCEDURE IDENTIFIER { function_head: function_specifier PROCEDURE IDENTIFIER {
scope = strdup($3); add_scope($3);
add_procedure($3);
symbol_t procedure; free($3);
procedure.name = $3;
add_procedure(procedure);
} }
; ;
@ -146,58 +153,23 @@ declaration_section: %empty
declaration: declaration:
variable_specifier type IDENTIFIER { variable_specifier type IDENTIFIER {
$$.type = $2; add_variable($2, $3);
$$.name = make_scoped_name(scope, $3);
$$.elements = 1;
add_variable($$);
free($3); free($3);
} }
| variable_specifier type IDENTIFIER '=' LITERAL { | variable_specifier type IDENTIFIER '=' LITERAL {
$$.type = $2; add_variable_with_value($2, $3, $5);
$$.name = make_scoped_name(scope, $3);
if (!can_fit($2, $5)) {
issue_warning("the value \033[1m'%lld'\033[0m will overflow in assignement", $5);
}
$$.elements = 1;
$$.value = $5;
add_variable($$);
free($3); free($3);
} }
| variable_specifier type '<' value '>' IDENTIFIER { | variable_specifier type '<' value '>' IDENTIFIER {
$$.type = $2; add_array_variable($2, $6, $4);
if (validate_array_size($4)) {
break;
}
$$.name = make_scoped_name(scope, $6);
$$.elements = $4;
add_variable($$);
free($6); free($6);
} }
| variable_specifier type '<' value '>' IDENTIFIER '=' ARRAY_LITERAL { | variable_specifier type '<' value '>' IDENTIFIER '=' ARRAY_LITERAL {
$$.type = $2; add_array_variable_with_value($2, $6, $4, $8.data, $8.len);
if (validate_array_size($4)) {
break;
}
if ((unsigned long long)$4 < $8.len) {
issue_warning("declared array size is smaller than assigned literal, this will cause truncation");
}
$$.name = make_scoped_name(scope, $6);
$$.elements = $4;
$$.array_value = $8.data;
add_variable($$);
free($6); free($6);
} }
| variable_specifier type '<' '>' IDENTIFIER '=' ARRAY_LITERAL { | variable_specifier type '<' '>' IDENTIFIER '=' ARRAY_LITERAL {
$$.type = $2; add_array_variable_with_value($2, $5, $7.len, $7.data, $7.len);
$$.name = make_scoped_name(scope, $5);
$$.elements = $7.len;
$$.array_value = $7.data;
add_variable($$);
free($5); free($5);
} }
; ;
@ -224,7 +196,6 @@ immediate: LITERAL {
symbol_t * variable = get_variable($1); symbol_t * variable = get_variable($1);
$$.type = REL; $$.type = REL;
$$.value = variable->_id; $$.value = variable->_id;
free($1); free($1);
} }
; ;
@ -239,9 +210,8 @@ dereference: '[' IDENTIFIER ']' { $$ = 0; /* XXX: how the fuck do i dereference?
; ;
relative: IDENTIFIER { relative: IDENTIFIER {
symbol_t * relative = get_symbol($1); $$ = get_relative($1)->_id;
/*breakpoint();*/ free($1);
$$ = relative->_id;
} }
; ;
@ -254,12 +224,8 @@ value: artimetric_block
} }
; ;
anon_variable: ARRAY_LITERAL { stored_literal: ARRAY_LITERAL {
$$.array_value = $1.data; add_literal($1.data, $1.len);
$$.elements = $1.len;
int ignore = asprintf(&$$.name, "_anon_%llu", anon_variable_counter++);
(void)ignore;
add_variable($$);
} }
; ;
@ -276,9 +242,7 @@ code: %empty
; ;
label: LABEL { label: LABEL {
symbol_t label; add_label($1, true);
label.name = make_scoped_name(scope, $1);
add_procedure(label);
} }
; ;
@ -337,7 +301,7 @@ arguments: %empty
| LITERAL arguments | LITERAL arguments
| register arguments | register arguments
| artimetric_block arguments | artimetric_block arguments
| anon_variable arguments | stored_literal arguments
; ;
register: register64s { $$ = $1; $$.size = D64; } register: register64s { $$ = $1; $$.size = D64; }
@ -436,7 +400,9 @@ artimetric_expression: %empty { $$ = 0; }
; ;
artimetric_operand: LITERAL artimetric_operand: LITERAL
| IDENTIFIER { $$ = 0; /*XXX*/ } | IDENTIFIER {
$$ = get_variable($1)->value;
}
; ;
exit: EXIT value { append_exit($2); } exit: EXIT value { append_exit($2); }

2
test/die.eax Normal file
View File

@ -0,0 +1,2 @@
program die
end program

14
test/forward_jump.eax Normal file
View File

@ -0,0 +1,14 @@
program forward
s8 <> heyo_data = "Heyo world\n"
begin
jmp lol
mov eax 1
mov edi 1
mov esi heyo_data
mov edx 12
syscall
lol:
exit 86
end program

View File

@ -1,4 +1,4 @@
; @BAKE fasm $@ $* ; @BAKE fasm $@ $*.out
format ELF64 executable 3 format ELF64 executable 3
segment readable executable segment readable executable