This commit is contained in:
anon 2024-07-16 18:56:55 +02:00
parent 7c6cdaae7f
commit fed0841193
6 changed files with 108 additions and 48 deletions

View File

@ -27,7 +27,10 @@ int compile_deinit(void) {
static
void dump_variable_to_assembler(void * data) {
variable_t * variable = (variable_t*)data;
symbol_t * variable = (symbol_t*)data;
if (variable->symbol_type != VARIABLE) {
return;
}
append_instructions(ASMDIRMEM, variable->_id, ASMDIRIMM, type2size(variable->type));
@ -44,7 +47,7 @@ void dump_variable_to_assembler(void * data) {
static
void dump_variables_to_assembler(void) {
tommy_hashtable_foreach(&variable_table, dump_variable_to_assembler);
tommy_hashtable_foreach(&symbol_table, dump_variable_to_assembler);
}
static

View File

@ -13,10 +13,6 @@ extern int compile(void);
extern void append_label (int rel);
extern void append_fastcall_begin (int rel);
extern void append_fastcall_end (void);
extern void append_fastcall_arguments (int rel, int wid, int imm);
/* --- Token appending
* The core problem is that we want an interface where we can append {instructoin}
* tokens without modifying the counter as that gets old fast and error prone

View File

@ -18,7 +18,7 @@ void debug_printf(const char * const fmt, ...) {
static
void dump_variable(void * data) {
variable_t * variable = (variable_t*)data;
symbol_t * variable = (symbol_t*)data;
if (variable->elements == 1) {
printf("{ .name = '%s', .value = '%ld' }\n",
variable->name,
@ -36,7 +36,7 @@ void dump_variable(void * data) {
static
void debug_dump_variables(void) {
tommy_hashtable_foreach(&variable_table, dump_variable);
tommy_hashtable_foreach(&symbol_table, dump_variable);
}
static

View File

@ -18,7 +18,8 @@
unsigned long long anon_variable_counter = 0;
tommy_hashtable variable_table;
static unsigned symbol_id = 0;
tommy_hashtable symbol_table;
int has_encountered_error = 0;
int is_program_found = 0;
@ -29,20 +30,20 @@ char * yyfilename = "";
int eaxhla_init(void) {
tommy_hashtable_init(&variable_table, 256);
tommy_hashtable_init(&symbol_table, 256);
return 0;
}
static
void free_variable(void * data) {
variable_t * variable = (variable_t*)data;
symbol_t * variable = (symbol_t*)data;
free(variable->name);
free(variable);
}
int eaxhla_deinit(void) {
tommy_hashtable_foreach(&variable_table, free_variable);
tommy_hashtable_done(&variable_table);
tommy_hashtable_foreach(&symbol_table, free_variable);
tommy_hashtable_done(&symbol_table);
return 0;
}
@ -50,31 +51,46 @@ int eaxhla_deinit(void) {
static
int table_compare_unsigned(const void * arg, const void * obj) {
return *(const unsigned *) arg != ((const variable_t*)obj)->_hash;
return *(const unsigned *) arg != ((const symbol_t*)obj)->_hash;
}
void add_variable(variable_t variable) {
static unsigned vid = 0;
void add_variable(symbol_t variable) {
if (get_variable(variable.name)) {
// XXX: this should say the varname, but this function does not know it
// in fact this source file should not be reporting errors,
// it should be returning an error and the parser should check.
issue_error("variable declared twice");
issue_error("symbol '%s' declared twice", variable.name);
return;
}
variable._id = vid++;
variable._id = symbol_id++;
// XXX this is cursed
variable_t * heap_variable = malloc(sizeof(variable));
symbol_t * heap_variable = malloc(sizeof(variable));
memcpy(heap_variable, &variable, sizeof(variable));
// */
heap_variable->_hash = tommy_strhash_u32(0, heap_variable->name);
tommy_hashtable_insert(&variable_table,
tommy_hashtable_insert(&symbol_table,
&heap_variable->_node,
heap_variable,
heap_variable->_hash
);
}
void add_procedure(symbol_t procedure) {
procedure._id = symbol_id++;
// XXX this is cursed
symbol_t * heap_procedure = malloc(sizeof(procedure));
memcpy(heap_procedure, &procedure, sizeof(procedure));
// */
heap_procedure->_hash = tommy_strhash_u32(0, heap_procedure->name);
tommy_hashtable_insert(&symbol_table,
&heap_procedure->_node,
heap_procedure,
heap_procedure->_hash
);
//
append_instructions(ASMDIRMEM, procedure._id);
}
/* Are these literals ugly? yes.
* However it would be much more painful to calculate the values inline.
*/
@ -161,16 +177,36 @@ char * make_scoped_name(const char * const scope, char * name) {
return r;
}
variable_t * get_variable(const char * const name) {
static
void * symbol_lookup(const char * const name) {
unsigned lookup_hash = tommy_strhash_u32(0, name);
variable_t * r = tommy_hashtable_search(&variable_table,
table_compare_unsigned,
&lookup_hash,
lookup_hash
);
void * r = tommy_hashtable_search(&symbol_table,
table_compare_unsigned,
&lookup_hash,
lookup_hash
);
return r;
}
symbol_t * get_variable(const char * const name) {
symbol_t *r = symbol_lookup(name);
if (r
&& r->symbol_type != VARIABLE) {
issue_error("the symbol '%s' is not a variable", name);
return NULL;
}
return r;
}
symbol_t * get_function(const char * const name) {
symbol_t * r = symbol_lookup(name);
if (r
&& r->symbol_type != FUNCTION) {
issue_error("the symbol '%s' is not a function", name);
return NULL;
}
return r;
}
void issue_warning(const char * const format, ...) {

View File

@ -4,21 +4,35 @@
#define WORD_SIZE_IN_BYTES (64/8)
typedef enum {
VARIABLE,
FUNCTION,
} symbol_type_t;
typedef struct {
union {
long value;
void * array_value;
};
unsigned long long elements;
char * name;
int type;
unsigned _id;
unsigned _hash;
tommy_node _node;
} variable_t;
symbol_type_t symbol_type;
union {
struct { // VARIABLE
int type;
unsigned long long elements;
union {
long value;
void * array_value;
};
};
struct { // FUNCTION
void * unused;
};
};
char * name;
unsigned _id;
unsigned _hash;
tommy_node _node;
} symbol_t;
extern tommy_hashtable variable_table;
extern tommy_hashtable symbol_table;
// Used for naming variables constructed from literals
extern unsigned long long anon_variable_counter;
typedef struct {
@ -43,8 +57,12 @@ extern char * make_scoped_name(const char * const scope, char * name);
extern int can_fit(int type, long long value);
extern int validate_array_size(int size);
extern void add_variable(variable_t variable);
extern variable_t * get_variable(const char * const name);
extern void add_variable(symbol_t variable);
extern symbol_t * get_variable(const char * const name);
//extern void add_function(symbol_t function);
extern symbol_t * get_function(const char * const name);
extern void add_procedure(symbol_t procedure);
extern int type2size(int type);

View File

@ -29,7 +29,7 @@
unsigned long long len;
void * data;
} blobval;
variable_t varval;
symbol_t varval;
cpuregister_t regval;
}
@ -127,10 +127,17 @@ system_specifier: UNIX { system_type = UNIX; }
;
// XXX: end procedure thing
function: function_head declaration_section MYBEGIN code END_PROCEDURE { scope = NULL; }
function: function_head declaration_section MYBEGIN code END_PROCEDURE {
scope = NULL;
append_instructions(RETN);
}
;
function_head: function_specifier PROCEDURE IDENTIFIER { scope = $3; }
function_head: function_specifier PROCEDURE IDENTIFIER {
scope = $3;
symbol_t procedure;
add_procedure(procedure);
}
;
function_specifier: %empty
@ -207,7 +214,7 @@ type: S8 { $$ = S8; }
immediate: LITERAL { $$.type = IMM; $$.value = $1; }
| IDENTIFIER {
char * varname = make_scoped_name(scope, $1);
variable_t * variable = get_variable(varname);
symbol_t * variable = get_variable(varname);
$$.type = REL;
$$.value = variable->_id;
free(varname);
@ -227,7 +234,7 @@ value: artimetric_block
| LITERAL
| IDENTIFIER {
char * varname = make_scoped_name(scope, $1);
variable_t * var = get_variable(varname);
symbol_t * var = get_variable(varname);
$$ = var->value;
free(var);
}
@ -292,9 +299,9 @@ machine_code: %empty
;
call: FASTCALL IDENTIFIER arguments {
//append_fastcall_begin(/**/);
//append_fastcall_arguments();
append_fastcall_end();
// XXX
symbol_t * function = get_function($2);
append_instructions(CALL, REL, function->_id);
free($2);
}
;