fucked shit up
This commit is contained in:
parent
4cbec3ec8a
commit
b0a54971b3
4
Makefile
4
Makefile
@ -76,8 +76,8 @@ ${OBJECT.d}/%.pluglock: ${OBJECT.d}/%.pp
|
||||
touch $@
|
||||
|
||||
test: ${OUT}
|
||||
ORIGIN="$$(realpath .)" PATH="$$(realpath .):${PATH}" cmdtest
|
||||
${WRAP} ./${OUT} test/nop.eax
|
||||
-ORIGIN="$$(realpath .)" PATH="$$(realpath .):${PATH}" cmdtest
|
||||
-${WRAP} ./${OUT} test/nop.eax
|
||||
|
||||
bootstrap:
|
||||
./library/bootstrap.sh
|
||||
|
@ -1,4 +1,5 @@
|
||||
#ifndef ASSEMBLER_H
|
||||
#define ASSEMBLER_H
|
||||
|
||||
enum {
|
||||
D8, // 8-bit
|
||||
@ -183,5 +184,4 @@ extern int was_instruction_array_empty;
|
||||
|
||||
extern void assemble (unsigned int count, unsigned int * array);
|
||||
|
||||
#define ASSEMBLER_H
|
||||
#endif
|
||||
|
@ -32,7 +32,7 @@ int compile_deinit(void) {
|
||||
static
|
||||
void dump_variable_to_assembler(void * data) {
|
||||
symbol_t * variable = (symbol_t*)data;
|
||||
if (variable->symbol_type != VARIABLE) {
|
||||
if (variable->symbol_type != VARIABLE_SYMBOL) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -6,12 +6,14 @@
|
||||
#include <stdarg.h>
|
||||
#include "eaxhla.h"
|
||||
|
||||
__attribute__((unused))
|
||||
static
|
||||
void breakpoint(void) { ; }
|
||||
|
||||
# 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, ...) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
@ -19,19 +21,22 @@ void debug_printf(const char * const fmt, ...) {
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
__attribute__((unused))
|
||||
static
|
||||
void dump_variable(void * data) {
|
||||
symbol_t * variable = (symbol_t*)data;
|
||||
if (variable->symbol_type != VARIABLE) { return; }
|
||||
if (variable->symbol_type != VARIABLE_SYMBOL) { return; }
|
||||
|
||||
if (variable->elements == 1) {
|
||||
printf("{ .name = '%s', .value = '%ld' }\n",
|
||||
printf("{ .name = '%s', .id = %d, .value = '%ld' }\n",
|
||||
variable->name,
|
||||
variable->_id,
|
||||
variable->value
|
||||
);
|
||||
} else {
|
||||
printf("{ .name = '%s', .elements = '%llu', .array_value = \"%.*s\" }\n",
|
||||
printf("{ .name = '%s', .id = %d, .elements = '%lu', .array_value = \"%.*s\" }\n",
|
||||
variable->name,
|
||||
variable->_id,
|
||||
variable->elements,
|
||||
(int)variable->elements,
|
||||
(char*)variable->array_value
|
||||
@ -39,28 +44,33 @@ void dump_variable(void * data) {
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((unused))
|
||||
static
|
||||
void debug_dump_variables(void) {
|
||||
puts("# Variables:");
|
||||
tommy_hashtable_foreach(&symbol_table, dump_variable);
|
||||
}
|
||||
|
||||
__attribute__((unused))
|
||||
static
|
||||
void dump_function(void * data) {
|
||||
symbol_t * function = (symbol_t*)data;
|
||||
if (function->symbol_type != FUNCTION) { return; }
|
||||
if (function->symbol_type != LABEL_SYMBOL) { return; }
|
||||
|
||||
printf("{ .name = '%s' }\n",
|
||||
function->name
|
||||
printf("{ .name = '%s', .id = %d }\n",
|
||||
function->name,
|
||||
function->_id
|
||||
);
|
||||
}
|
||||
|
||||
__attribute__((unused))
|
||||
static
|
||||
void debug_dump_functions(void) {
|
||||
puts("# Functions:");
|
||||
tommy_hashtable_foreach(&symbol_table, dump_function);
|
||||
}
|
||||
|
||||
__attribute__((unused))
|
||||
static
|
||||
void debug_dump_symbols(void) {
|
||||
debug_dump_variables();
|
||||
@ -68,6 +78,7 @@ void debug_dump_symbols(void) {
|
||||
printf("# Total variable size: '%d'\n", variable_size_sum());
|
||||
}
|
||||
|
||||
__attribute__((unused))
|
||||
static
|
||||
void debug_token_dump(void) {
|
||||
extern unsigned int * token_array;
|
||||
|
393
source/eaxhla.c
393
source/eaxhla.c
@ -9,6 +9,7 @@
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "eaxhla.tab.h"
|
||||
|
||||
@ -16,7 +17,14 @@
|
||||
#include "assembler.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;
|
||||
tommy_hashtable symbol_table;
|
||||
@ -38,6 +46,15 @@ int eaxhla_init(void) {
|
||||
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
|
||||
void free_symbol(void * data) {
|
||||
symbol_t * variable = (symbol_t*)data;
|
||||
@ -46,96 +63,19 @@ void free_symbol(void * data) {
|
||||
}
|
||||
|
||||
int eaxhla_deinit(void) {
|
||||
empty_out_scope();
|
||||
|
||||
tommy_hashtable_foreach(&symbol_table, free_symbol);
|
||||
tommy_hashtable_done(&symbol_table);
|
||||
|
||||
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.
|
||||
* However it would be much more painful to calculate the values inline.
|
||||
*/
|
||||
int can_fit(const int type, const long long value) {
|
||||
unsigned long long max = 0;
|
||||
size_t max = 0;
|
||||
long long min = 0;
|
||||
switch (type) {
|
||||
case U8: {
|
||||
@ -167,9 +107,216 @@ int can_fit(const int type, const long long value) {
|
||||
max = 4294967295;
|
||||
} 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) {
|
||||
switch (type) {
|
||||
case U8:
|
||||
@ -205,7 +352,7 @@ int size2bytes(const int size) {
|
||||
static
|
||||
void _variable_size_sum_iteration(void * i, void * data) {
|
||||
symbol_t * variable = (symbol_t*)data;
|
||||
if (variable->symbol_type != VARIABLE) { return; }
|
||||
if (variable->symbol_type != VARIABLE_SYMBOL) { return; }
|
||||
|
||||
int * sum = i;
|
||||
|
||||
@ -218,54 +365,13 @@ int variable_size_sum(void) {
|
||||
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 * r;
|
||||
char * varname = make_scoped_name(scope, name);
|
||||
|
||||
r = symbol_lookup(varname);
|
||||
if (r
|
||||
&& r->symbol_type != VARIABLE) {
|
||||
&& r->symbol_type != VARIABLE_SYMBOL) {
|
||||
issue_error("the symbol '%s' is not a variable", name);
|
||||
return NULL;
|
||||
}
|
||||
@ -276,13 +382,46 @@ symbol_t * get_function(const char * const name) {
|
||||
symbol_t * r;
|
||||
r = symbol_lookup(name);
|
||||
if (r
|
||||
&& r->symbol_type != FUNCTION) {
|
||||
&& r->symbol_type != LABEL_SYMBOL) {
|
||||
issue_error("the symbol '%s' is not a function", name);
|
||||
return NULL;
|
||||
}
|
||||
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, ...) {
|
||||
extern char * yyfilename;
|
||||
|
@ -1,27 +1,29 @@
|
||||
#ifndef EAXHLA_H
|
||||
#define EAXHLA_H
|
||||
|
||||
#include <tommyds/tommyds/tommyhashtbl.h>
|
||||
|
||||
#define WORD_SIZE_IN_BYTES (64/8)
|
||||
|
||||
// XXX these should be private
|
||||
typedef enum {
|
||||
VARIABLE,
|
||||
FUNCTION,
|
||||
VARIABLE_SYMBOL,
|
||||
LABEL_SYMBOL,
|
||||
} symbol_type_t;
|
||||
|
||||
typedef struct {
|
||||
symbol_type_t symbol_type;
|
||||
union {
|
||||
struct { // VARIABLE
|
||||
struct { // VARIABLE_SYMBOL
|
||||
int type;
|
||||
unsigned long long elements;
|
||||
size_t elements;
|
||||
union {
|
||||
long value;
|
||||
void * array_value;
|
||||
};
|
||||
};
|
||||
struct { // FUNCTION
|
||||
void * unused;
|
||||
struct { // LABEL_SYMBOL
|
||||
int is_resolved;
|
||||
};
|
||||
};
|
||||
char * name;
|
||||
@ -30,10 +32,12 @@ typedef struct {
|
||||
tommy_node _node;
|
||||
} 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 unsigned long long anon_variable_counter;
|
||||
extern tommy_hashtable symbol_table;
|
||||
|
||||
typedef struct {
|
||||
unsigned number : 6;
|
||||
@ -42,39 +46,54 @@ typedef struct {
|
||||
|
||||
extern int system_type;
|
||||
|
||||
/* Used for error discovery
|
||||
*/
|
||||
extern int is_program_found;
|
||||
extern int has_encountered_error;
|
||||
|
||||
extern char * scope;
|
||||
extern void empty_out_scope(void);
|
||||
|
||||
// Used for error reporting
|
||||
/* Used for error reporting
|
||||
*/
|
||||
extern char * yyfilename;
|
||||
|
||||
extern int eaxhla_init(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);
|
||||
|
||||
// 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_error(const char * format, ...);
|
||||
|
||||
#define EAXHLA_H
|
||||
#endif
|
||||
|
@ -1,6 +1,7 @@
|
||||
%{
|
||||
#include <stdlib.h>
|
||||
#include "sds/sds.h"
|
||||
#include "eaxhla.h"
|
||||
#include "eaxhla.tab.h"
|
||||
|
||||
sds string_literal_buffer;
|
||||
@ -253,13 +254,13 @@ library { BEGIN INITIAL; return END_LIBRARY; }
|
||||
<IN_COMMENT>{
|
||||
\n { BEGIN INITIAL; }
|
||||
.* { ; }
|
||||
<<EOF>> { yytext = strdup("<EOF>"); issue_error("unterminated comment"); yyterminate(); }
|
||||
<<EOF>> { issue_error("unterminated comment"); yyterminate(); }
|
||||
}
|
||||
|
||||
<IN_MULTILINE_COMMENT>{
|
||||
\*\/ { BEGIN INITIAL; }
|
||||
.|\n { ; }
|
||||
<<EOF>> { yytext = strdup("<EOF>"); issue_error("unterminated comment"); yyterminate(); }
|
||||
<<EOF>> { issue_error("unterminated comment"); yyterminate(); }
|
||||
}
|
||||
|
||||
<INITIAL,IN_ARTIMETRIC_BLOCK>{
|
||||
@ -285,7 +286,7 @@ library { BEGIN INITIAL; return END_LIBRARY; }
|
||||
}
|
||||
|
||||
<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; }
|
||||
|
@ -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 {
|
||||
#include "eaxhla.h"
|
||||
}
|
||||
%{
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "eaxhla.h"
|
||||
#include "eaxhla.yy.h"
|
||||
#include "assembler.h"
|
||||
#include "compile.h"
|
||||
#include "eaxhla.h"
|
||||
#include "debug.h"
|
||||
|
||||
extern void yyfree_leftovers(void);
|
||||
@ -70,7 +77,7 @@
|
||||
%token U8 U16 U32 U64
|
||||
%type<intval> type
|
||||
%type<varval> declaration
|
||||
%type<varval> anon_variable
|
||||
%type<varval> stored_literal
|
||||
|
||||
// Registers
|
||||
%type<regval> register register64s register32s register16s register8s
|
||||
@ -94,6 +101,9 @@
|
||||
%token EXIT BREAK
|
||||
%%
|
||||
|
||||
document: hla { fin_hla(); }
|
||||
;
|
||||
|
||||
hla: %empty
|
||||
// | library hla
|
||||
| declaration hla // tmp
|
||||
@ -102,11 +112,11 @@ hla: %empty
|
||||
;
|
||||
|
||||
program: program_head declaration_section MYBEGIN code END_PROGRAM {
|
||||
empty_out_scope();
|
||||
}
|
||||
;
|
||||
|
||||
program_head: program_specifier PROGRAM IDENTIFIER {
|
||||
add_scope($3);
|
||||
add_program($3);
|
||||
free($3);
|
||||
};
|
||||
@ -121,17 +131,14 @@ system_specifier: UNIX { system_type = UNIX; }
|
||||
|
||||
// XXX: end procedure thing
|
||||
function: function_head declaration_section MYBEGIN code END_PROCEDURE {
|
||||
append_instructions(RETN);
|
||||
empty_out_scope();
|
||||
fin_procedure();
|
||||
}
|
||||
;
|
||||
|
||||
function_head: function_specifier PROCEDURE IDENTIFIER {
|
||||
scope = strdup($3);
|
||||
|
||||
symbol_t procedure;
|
||||
procedure.name = $3;
|
||||
add_procedure(procedure);
|
||||
add_scope($3);
|
||||
add_procedure($3);
|
||||
free($3);
|
||||
}
|
||||
;
|
||||
|
||||
@ -146,58 +153,23 @@ declaration_section: %empty
|
||||
|
||||
declaration:
|
||||
variable_specifier type IDENTIFIER {
|
||||
$$.type = $2;
|
||||
$$.name = make_scoped_name(scope, $3);
|
||||
$$.elements = 1;
|
||||
add_variable($$);
|
||||
|
||||
add_variable($2, $3);
|
||||
free($3);
|
||||
}
|
||||
| variable_specifier type IDENTIFIER '=' LITERAL {
|
||||
$$.type = $2;
|
||||
$$.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($$);
|
||||
|
||||
add_variable_with_value($2, $3, $5);
|
||||
free($3);
|
||||
}
|
||||
| variable_specifier type '<' value '>' IDENTIFIER {
|
||||
$$.type = $2;
|
||||
if (validate_array_size($4)) {
|
||||
break;
|
||||
}
|
||||
$$.name = make_scoped_name(scope, $6);
|
||||
$$.elements = $4;
|
||||
add_variable($$);
|
||||
|
||||
add_array_variable($2, $6, $4);
|
||||
free($6);
|
||||
}
|
||||
| variable_specifier type '<' value '>' IDENTIFIER '=' ARRAY_LITERAL {
|
||||
$$.type = $2;
|
||||
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($$);
|
||||
|
||||
add_array_variable_with_value($2, $6, $4, $8.data, $8.len);
|
||||
free($6);
|
||||
}
|
||||
| variable_specifier type '<' '>' IDENTIFIER '=' ARRAY_LITERAL {
|
||||
$$.type = $2;
|
||||
$$.name = make_scoped_name(scope, $5);
|
||||
$$.elements = $7.len;
|
||||
$$.array_value = $7.data;
|
||||
add_variable($$);
|
||||
|
||||
add_array_variable_with_value($2, $5, $7.len, $7.data, $7.len);
|
||||
free($5);
|
||||
}
|
||||
;
|
||||
@ -224,7 +196,6 @@ immediate: LITERAL {
|
||||
symbol_t * variable = get_variable($1);
|
||||
$$.type = REL;
|
||||
$$.value = variable->_id;
|
||||
|
||||
free($1);
|
||||
}
|
||||
;
|
||||
@ -239,9 +210,8 @@ dereference: '[' IDENTIFIER ']' { $$ = 0; /* XXX: how the fuck do i dereference?
|
||||
;
|
||||
|
||||
relative: IDENTIFIER {
|
||||
symbol_t * relative = get_symbol($1);
|
||||
/*breakpoint();*/
|
||||
$$ = relative->_id;
|
||||
$$ = get_relative($1)->_id;
|
||||
free($1);
|
||||
}
|
||||
;
|
||||
|
||||
@ -254,12 +224,8 @@ value: artimetric_block
|
||||
}
|
||||
;
|
||||
|
||||
anon_variable: ARRAY_LITERAL {
|
||||
$$.array_value = $1.data;
|
||||
$$.elements = $1.len;
|
||||
int ignore = asprintf(&$$.name, "_anon_%llu", anon_variable_counter++);
|
||||
(void)ignore;
|
||||
add_variable($$);
|
||||
stored_literal: ARRAY_LITERAL {
|
||||
add_literal($1.data, $1.len);
|
||||
}
|
||||
;
|
||||
|
||||
@ -276,9 +242,7 @@ code: %empty
|
||||
;
|
||||
|
||||
label: LABEL {
|
||||
symbol_t label;
|
||||
label.name = make_scoped_name(scope, $1);
|
||||
add_procedure(label);
|
||||
add_label($1, true);
|
||||
}
|
||||
;
|
||||
|
||||
@ -337,7 +301,7 @@ arguments: %empty
|
||||
| LITERAL arguments
|
||||
| register arguments
|
||||
| artimetric_block arguments
|
||||
| anon_variable arguments
|
||||
| stored_literal arguments
|
||||
;
|
||||
|
||||
register: register64s { $$ = $1; $$.size = D64; }
|
||||
@ -436,7 +400,9 @@ artimetric_expression: %empty { $$ = 0; }
|
||||
;
|
||||
|
||||
artimetric_operand: LITERAL
|
||||
| IDENTIFIER { $$ = 0; /*XXX*/ }
|
||||
| IDENTIFIER {
|
||||
$$ = get_variable($1)->value;
|
||||
}
|
||||
;
|
||||
|
||||
exit: EXIT value { append_exit($2); }
|
||||
|
2
test/die.eax
Normal file
2
test/die.eax
Normal file
@ -0,0 +1,2 @@
|
||||
program die
|
||||
end program
|
14
test/forward_jump.eax
Normal file
14
test/forward_jump.eax
Normal 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
|
@ -1,4 +1,4 @@
|
||||
; @BAKE fasm $@ $*
|
||||
; @BAKE fasm $@ $*.out
|
||||
format ELF64 executable 3
|
||||
|
||||
segment readable executable
|
||||
|
Loading…
x
Reference in New Issue
Block a user