CC ?= clang
-CFLAGS += -Wall -pedantic-errors -std=c99
+CFLAGS += -Wall -pedantic-errors -std=c90
OBJ = main.o \
lex.o \
error.o \
* globals with no assignments are globals. Function body types
* are locals.
*/
-static inline bool asm_parse_type(const char *skip, size_t line, asm_state *state) {
+static GMQCC_INLINE bool asm_parse_type(const char *skip, size_t line, asm_state *state) {
if (!(strstr(skip, "FLOAT:") == &skip[0]) &&
(strstr(skip, "VECTOR:") == &skip[0]) &&
(strstr(skip, "ENTITY:") == &skip[0]) &&
* names among other things. Ensures valid name as well, and even
* internal engine function selection.
*/
-static inline bool asm_parse_func(const char *skip, size_t line, asm_state *state) {
+static GMQCC_INLINE bool asm_parse_func(const char *skip, size_t line, asm_state *state) {
if (*state == ASM_FUNCTION && (strstr(skip, "FUNCTION:") == &skip[0]))
return false;
* to determine this.
*/
if (strchr(name, ',')) {
+ prog_section_function function;
+ prog_section_def def;
+
char *find = strchr(name, ',') + 1;
/* skip whitespace */
* global (optional)
* name
*/
- code_functions_add((prog_section_function){
- -atoi(find), /* needs to be negated */
- 0, 0, 0,
- .name = code_chars_elements,
- 0, 0,{0}
- });
- code_defs_add((prog_section_def){
- .type = TYPE_FUNCTION,
- .offset = code_globals_elements,
- .name = code_chars_elements
- });
- code_globals_add(code_chars_elements);
-
- code_chars_put(name, strlen(name));
- code_chars_add('\0');
+ function.entry = -atoi(find);
+ function.firstlocal = 0;
+ function.profile = 0;
+ function.name = code_chars_elements;
+ function.file = 0;
+ function.nargs = 0;
+ def.type = TYPE_FUNCTION;
+ def.offset = code_globals_elements;
+ def.name = code_chars_elements;
+ code_functions_add(function);
+ code_defs_add (def);
+ code_globals_add (code_chars_elements);
+ code_chars_put (name, strlen(name));
+ code_chars_add ('\0');
/*
* Sanatize the numerical constant used to select the
printf("invalid internal function identifier, must be all numeric\n");
} else {
- /* TODO: function bodies */
+ printf("Found function %s\n", name);
}
mem_d(copy);
#include "gmqcc.h"
#include "ast.h"
-#define ast_instantiate(T, ctx, destroyfn) \
- T *self = (T*)mem_a(sizeof(T)); \
- ast_node_init((ast_node*)self, ctx); \
- ( (ast_node*)self )->node.destroy = (ast_node_delete*)destroyfn;
+#define ast_instantiate(T, ctx, destroyfn) \
+ T* self = (T*)mem_a(sizeof(T)); \
+ ast_node_init((ast_node*)self, ctx); \
+ ( (ast_node*)self )->node.destroy = (ast_node_delete*)destroyfn
/* It must not be possible to get here. */
static void _ast_node_destroy(ast_node *self)
ast_function* ast_function_new(lex_ctx ctx, const char *name, ast_value *vtype)
{
+ ast_instantiate(ast_function, ctx, ast_function_delete);
+
if (!vtype)
return NULL;
if (vtype->isconst)
if (vtype->vtype != TYPE_FUNCTION)
return NULL;
- ast_instantiate(ast_function, ctx, ast_function_delete);
-
self->vtype = vtype;
self->name = name ? util_strdup(name) : NULL;
MEM_VECTOR_INIT(self, blocks);
bool ast_global_codegen(ast_value *self, ir_builder *ir)
{
+ ir_value *v = NULL;
if (self->isconst && self->vtype == TYPE_FUNCTION)
{
ir_function *func = ir_builder_create_function(ir, self->name);
return true;
}
- ir_value *v = ir_builder_create_global(ir, self->name, self->vtype);
+ v = ir_builder_create_global(ir, self->name, self->vtype);
if (!v)
return false;
VECTOR_MAKE(char, code_chars );
void code_init() {
+ prog_section_function empty_function = {0,0,0,0,0,0,0,{0}};
+ prog_section_statement empty_statement = {0,{0},{0},{0}};
+ int i = 0;
+
/* omit creation of null code */
if (opts_omit_nullcode)
return;
* The way progs.dat is suppose to work is odd, there needs to be
* some null (empty) statements, functions, and 28 globals
*/
- prog_section_function empty_function = {0,0,0,0,0,0,0,{0}};
- prog_section_statement empty_statement = {0,{0},{0},{0}};
- int i;
- for(i = 0; i < 28; i++)
+ for(; i < 28; i++)
code_globals_add(0);
code_chars_add ('\0');
}
void code_test() {
+ prog_section_def d1 = { TYPE_VOID, 28, 1 };
+ prog_section_def d2 = { TYPE_FUNCTION, 29, 8 };
+ prog_section_def d3 = { TYPE_STRING, 30, 14};
+ prog_section_function f1 = { 1, 0, 0, 0, 1, 0,0, {0}};
+ prog_section_function f2 = {-4, 0, 0, 0, 8, 0,0, {0}};
+ prog_section_function f3 = { 0, 0, 0, 0, 14+13, 0,0, {0}};
+ prog_section_function f4 = { 0, 0, 0, 0, 14+13+10, 0,0, {0}};
+ prog_section_function f5 = { 0, 0, 0, 0, 14+13+10+7, 0,0, {0}};
+ prog_section_function f6 = { 0, 0, 0, 0, 14+13+10+7+9, 0,0, {0}};
+ prog_section_statement s1 = { INSTR_STORE_F, {30}, {OFS_PARM0}, {0}};
+ prog_section_statement s2 = { INSTR_CALL1, {29}, {0}, {0}};
+ prog_section_statement s3 = { INSTR_RETURN, {0}, {0}, {0}};
+
code_chars_put("m_init", 0x6);
code_chars_put("print", 0x5);
code_chars_put("hello world\n", 0xC);
code_globals_add(14); /* hello world in string table */
/* now the defs */
- code_defs_add((prog_section_def){.type=TYPE_VOID, .offset=28/*globals[28]*/, .name=1 }); /* m_init */
- code_defs_add((prog_section_def){.type=TYPE_FUNCTION,.offset=29/*globals[29]*/, .name=8 }); /* print */
- code_defs_add((prog_section_def){.type=TYPE_STRING, .offset=30/*globals[30]*/, .name=14}); /*hello_world*/
-
- code_functions_add((prog_section_function){1, 0, 0, 0, .name=1, 0, 0, {0}}); /* m_init */
- code_functions_add((prog_section_function){-4, 0, 0, 0, .name=8, 0, 0, {0}}); /* print */
- code_functions_add((prog_section_function){0, 0, 0, 0, .name=14+13, 0,0, {0}}); /* m_keydown */
- code_functions_add((prog_section_function){0, 0, 0, 0, .name=14+13+10, 0,0, {0}});
- code_functions_add((prog_section_function){0, 0, 0, 0, .name=14+13+10+7, 0,0, {0}});
- code_functions_add((prog_section_function){0, 0, 0, 0, .name=14+13+10+7+9, 0,0, {0}});
-
- code_statements_add((prog_section_statement){INSTR_STORE_F, {30}/*30 is hello_world */, {OFS_PARM0}, {0}});
- code_statements_add((prog_section_statement){INSTR_CALL1, {29}/*29 is print */, {0}, {0}});
- code_statements_add((prog_section_statement){INSTR_RETURN, {0}, {0}, {0}});
+ code_defs_add (d1); /* m_init */
+ code_defs_add (d2); /* print */
+ code_defs_add (d3); /*hello_world*/
+ code_functions_add (f1); /* m_init */
+ code_functions_add (f2); /* print */
+ code_functions_add (f3); /* m_keydown */
+ code_functions_add (f4);
+ code_functions_add (f5);
+ code_functions_add (f6);
+ code_statements_add(s1);
+ code_statements_add(s2);
+ code_statements_add(s3);
}
void code_write() {
- prog_header code_header={0};
+ prog_header code_header = {0};
+ prog_section statements;
+ prog_section defs;
+ prog_section fields;
+ prog_section functions;
+ prog_section globals;
+ prog_section strings;
+ FILE *fp = NULL;
+ size_t it = 1;
/* see proposal.txt */
if (opts_omit_nullcode) {
code_header.flags = 1;
}
+ statements.offset = sizeof(prog_header);
+ statements.length = code_statements_elements;
+ defs.offset = code_header.statements.offset + sizeof(prog_section_statement) * code_statements_elements;
+ defs.length = code_defs_elements;
+ fields.offset = code_header.defs.offset + sizeof(prog_section_def) * code_defs_elements;
+ fields.length = code_fields_elements;
+ functions.offset = code_header.fields.offset + sizeof(prog_section_field) * code_fields_elements;
+ functions.length = code_functions_elements;
+ globals.offset = code_header.functions.offset + sizeof(prog_section_function) * code_functions_elements;
+ globals.length = code_globals_elements;
+ strings.offset = code_header.globals.offset + sizeof(int) * code_globals_elements;
+ strings.length = code_chars_elements;
+
code_header.version = 6;
code_header.crc16 = 0; /* TODO: */
- code_header.statements = (prog_section){sizeof(prog_header), code_statements_elements };
- code_header.defs = (prog_section){code_header.statements.offset + sizeof(prog_section_statement)*code_statements_elements, code_defs_elements };
- code_header.fields = (prog_section){code_header.defs.offset + sizeof(prog_section_def) *code_defs_elements, code_fields_elements };
- code_header.functions = (prog_section){code_header.fields.offset + sizeof(prog_section_field) *code_fields_elements, code_functions_elements };
- code_header.globals = (prog_section){code_header.functions.offset + sizeof(prog_section_function) *code_functions_elements, code_globals_elements };
- code_header.strings = (prog_section){code_header.globals.offset + sizeof(int) *code_globals_elements, code_chars_elements };
+ code_header.statements = statements;
+ code_header.defs = defs;
+ code_header.fields = fields;
+ code_header.functions = functions;
+ code_header.globals = globals;
+ code_header.strings = strings;
code_header.entfield = 0; /* TODO: */
if (opts_darkplaces_stringtablebug) {
}
/* ensure all data is in LE format */
- util_endianswap(&code_header, 1, sizeof(prog_header));
- util_endianswap(code_statements_data, code_statements_elements, sizeof(prog_section_statement));
- util_endianswap(code_defs_data, code_defs_elements, sizeof(prog_section_def));
- util_endianswap(code_fields_data, code_fields_elements, sizeof(prog_section_field));
- util_endianswap(code_functions_data, code_functions_elements, sizeof(prog_section_function));
- util_endianswap(code_globals_data, code_globals_elements, sizeof(int));
-
- FILE *fp = fopen("program.dat", "wb");
- fwrite(&code_header, 1, sizeof(prog_header), fp);
- fwrite(code_statements_data, 1, sizeof(prog_section_statement)*code_statements_elements, fp);
- fwrite(code_defs_data, 1, sizeof(prog_section_def) *code_defs_elements, fp);
- fwrite(code_fields_data, 1, sizeof(prog_section_field) *code_fields_elements, fp);
- fwrite(code_functions_data, 1, sizeof(prog_section_function) *code_functions_elements, fp);
- fwrite(code_globals_data, 1, sizeof(int) *code_globals_elements, fp);
- fwrite(code_chars_data, 1, 1 *code_chars_elements, fp);
+ util_endianswap(&code_header, 1, sizeof(prog_header));
+ util_endianswap (code_statements_data, code_statements_elements, sizeof(prog_section_statement));
+ util_endianswap (code_defs_data, code_defs_elements, sizeof(prog_section_def));
+ util_endianswap (code_fields_data, code_fields_elements, sizeof(prog_section_field));
+ util_endianswap (code_functions_data, code_functions_elements, sizeof(prog_section_function));
+ util_endianswap (code_globals_data, code_globals_elements, sizeof(int));
+
+ fp = fopen("program.dat", "wb");
+ fwrite(&code_header, 1, sizeof(prog_header), fp);
+ fwrite (code_statements_data, 1, sizeof(prog_section_statement)*code_statements_elements, fp);
+ fwrite (code_defs_data, 1, sizeof(prog_section_def) *code_defs_elements, fp);
+ fwrite (code_fields_data, 1, sizeof(prog_section_field) *code_fields_elements, fp);
+ fwrite (code_functions_data, 1, sizeof(prog_section_function) *code_functions_elements, fp);
+ fwrite (code_globals_data, 1, sizeof(int) *code_globals_elements, fp);
+ fwrite (code_chars_data, 1, 1 *code_chars_elements, fp);
util_debug("GEN","HEADER:\n");
util_debug("GEN"," version: = %d\n", code_header.version );
/* FUNCTIONS */
util_debug("GEN", "FUNCTIONS:\n");
- size_t i = 1;
- for (; i < code_functions_elements; i++) {
- size_t j = code_functions_data[i].entry;
+ for (; it < code_functions_elements; it++) {
+ size_t j = code_functions_data[it].entry;
util_debug("GEN", " {.entry =% 5d, .firstlocal =% 5d, .locals =% 5d, .profile =% 5d, .name =% 5d, .file =% 5d, .nargs =% 5d, .argsize =%0X }\n",
- code_functions_data[i].entry,
- code_functions_data[i].firstlocal,
- code_functions_data[i].locals,
- code_functions_data[i].profile,
- code_functions_data[i].name,
- code_functions_data[i].file,
- code_functions_data[i].nargs,
- *((int32_t*)&code_functions_data[i].argsize)
+ code_functions_data[it].entry,
+ code_functions_data[it].firstlocal,
+ code_functions_data[it].locals,
+ code_functions_data[it].profile,
+ code_functions_data[it].name,
+ code_functions_data[it].file,
+ code_functions_data[it].nargs,
+ *((int32_t*)&code_functions_data[it].argsize)
);
- util_debug("GEN", " NAME: %s\n", &code_chars_data[code_functions_data[i].name]);
+ util_debug("GEN", " NAME: %s\n", &code_chars_data[code_functions_data[it].name]);
/* Internal functions have no code */
- if (code_functions_data[i].entry >= 0) {
+ if (code_functions_data[it].entry >= 0) {
util_debug("GEN", " CODE:\n");
for (;;) {
if (code_statements_data[j].opcode != INSTR_DONE &&
*/
#define GMQCC_SUPRESS_EMPTY_BODY do { } while (0)
+/*
+ * Inline is not supported in < C90, however some compilers
+ * like gcc and clang might have an inline attribute we can
+ * use if present.
+ */
+#if __STDC_VERSION__ < 199901L
+# if defined(__GNUC__) || defined (__CLANG__)
+# if __GNUC__ < 2
+# define GMQCC_INLINE
+# else
+# define GMQCC_INLINE __attribute__ ((always_inline))
+# endif
+# else
+# define GMQCC_INLINE
+# endif
+#else
+# define GMQCC_INLINE inline
+#endif
+
/*
* stdint.h and inttypes.h -less subset
* for systems that don't have it, which we must
#if INT_MAX == 0x7FFFFFFF
typedef int int32_t;
typedef unsigned int uint32_t;
+ typedef long int64_t;
+ typedef unsigned long uint64_t;
#elif LONG_MAX == 0x7FFFFFFF
typedef long int32_t;
typedef unsigned long uint32_t;
+
+ /* bail on 64 bit type! */
+ typedef char int64_t;
+ typedef char uint64_t;
#endif
#ifdef _LP64 /* long pointer == 64 */
typedef unsigned long uintptr_t;
typedef char uint8_size_is_correct [sizeof(uint8_t) == 1?1:-1];
typedef char uint16_size_if_correct [sizeof(uint16_t) == 2?1:-1];
typedef char uint32_size_is_correct [sizeof(uint32_t) == 4?1:-1];
+typedef char uint64_size_is_correct [sizeof(uint64_t) == 8?1:-1];
typedef char int16_size_if_correct [sizeof(int16_t) == 2?1:-1];
typedef char int32_size_is_correct [sizeof(int32_t) == 4?1:-1];
+typedef char int64_size_is_correct [sizeof(int64_t) == 8?1:-1];
/* intptr_t / uintptr_t correct size check */
typedef char uintptr_size_is_correct[sizeof(intptr_t) == sizeof(int*)?1:-1];
typedef char intptr_size_is_correct [sizeof(uintptr_t)== sizeof(int*)?1:-1];
-//===================================================================
-//============================ lex.c ================================
-//===================================================================
+/*===================================================================*/
+/*============================ lex.c ================================*/
+/*===================================================================*/
typedef struct lex_file_t {
FILE *file; /* file handler */
char *name; /* name of file */
TOKEN_CONTINUE ,
TOKEN_RETURN ,
TOKEN_GOTO ,
- TOKEN_FOR , // extension
- TOKEN_TYPEDEF , // extension
+ TOKEN_FOR , /* extension */
+ TOKEN_TYPEDEF , /* extension */
- // ensure the token types are out of the
- // bounds of anyothers that may conflict.
+ /* ensure the token types are out of the */
+ /* bounds of anyothers that may conflict. */
TOKEN_FLOAT = 110,
TOKEN_VECTOR ,
TOKEN_STRING ,
lex_file *lex_include(lex_file *, const char *);
void lex_init (const char *, lex_file **);
-//===================================================================
-//========================== error.c ================================
-//===================================================================
+/*===================================================================*/
+/*========================== error.c ================================*/
+/*===================================================================*/
#define ERROR_LEX (SHRT_MAX+0)
#define ERROR_PARSE (SHRT_MAX+1)
#define ERROR_INTERNAL (SHRT_MAX+2)
#define ERROR_PREPRO (SHRT_MAX+4)
int error(lex_file *, int, const char *, ...);
-//===================================================================
-//========================== parse.c ================================
-//===================================================================
+/*===================================================================*/
+/*========================== parse.c ================================*/
+/*===================================================================*/
int parse_gen(lex_file *);
-//===================================================================
-//========================== typedef.c ==============================
-//===================================================================
+/*===================================================================*/
+/*========================== typedef.c ==============================*/
+/*===================================================================*/
typedef struct typedef_node_t {
char *name;
} typedef_node;
int typedef_add (lex_file *file, const char *, const char *);
-//===================================================================
-//=========================== util.c ================================
-//===================================================================
+/*===================================================================*/
+/*=========================== util.c ================================*/
+/*===================================================================*/
void *util_memory_a (unsigned int, unsigned int, const char *);
void util_memory_d (void *, unsigned int, const char *);
void util_meminfo ();
/* Builds vector add */
#define VECTOR_CORE(T,N) \
int N##_add(T element) { \
+ void *temp = NULL; \
if (N##_elements == N##_allocated) { \
if (N##_allocated == 0) { \
N##_allocated = 12; \
} else { \
N##_allocated *= 2; \
} \
- void *temp = mem_a(N##_allocated * sizeof(T)); \
- if (!temp) { \
+ if (!(temp = mem_a(N##_allocated * sizeof(T)))) { \
mem_d(temp); \
return -1; \
} \
VECTOR_TYPE(T,N); \
VECTOR_CORE(T,N)
-//===================================================================
-//=========================== code.c ================================
-//===================================================================
+/*===================================================================*/
+/*=========================== code.c ================================*/
+/*===================================================================*/
enum {
TYPE_VOID ,
TYPE_STRING ,
TYPE_FUNCTION ,
TYPE_POINTER ,
/* TYPE_INTEGER , */
- TYPE_VARIANT ,
+ TYPE_VARIANT
};
/*
*/
VINSTR_PHI,
VINSTR_JUMP,
- VINSTR_COND,
+ VINSTR_COND
};
/*
void code_write ();
void code_init ();
-//===================================================================
-//========================= assembler.c =============================
-//===================================================================
+/*===================================================================*/
+/*========================= assembler.c =============================*/
+/*===================================================================*/
static const struct {
const char *m; /* menomic */
const size_t o; /* operands */
const size_t l; /* menomic len */
-} const asm_instr[] = {
- [INSTR_DONE] = { "DONE" , 1, 4 },
- [INSTR_MUL_F] = { "MUL_F" , 3, 5 },
- [INSTR_MUL_V] = { "MUL_V" , 3, 5 },
- [INSTR_MUL_FV] = { "MUL_FV" , 3, 6 },
- [INSTR_MUL_VF] = { "MUL_VF" , 3, 6 },
- [INSTR_DIV_F] = { "DIV" , 0, 3 },
- [INSTR_ADD_F] = { "ADD_F" , 3, 5 },
- [INSTR_ADD_V] = { "ADD_V" , 3, 5 },
- [INSTR_SUB_F] = { "SUB_F" , 3, 5 },
- [INSTR_SUB_V] = { "DUB_V" , 3, 5 },
- [INSTR_EQ_F] = { "EQ_F" , 0, 4 },
- [INSTR_EQ_V] = { "EQ_V" , 0, 4 },
- [INSTR_EQ_S] = { "EQ_S" , 0, 4 },
- [INSTR_EQ_E] = { "EQ_E" , 0, 4 },
- [INSTR_EQ_FNC] = { "ES_FNC" , 0, 6 },
- [INSTR_NE_F] = { "NE_F" , 0, 4 },
- [INSTR_NE_V] = { "NE_V" , 0, 4 },
- [INSTR_NE_S] = { "NE_S" , 0, 4 },
- [INSTR_NE_E] = { "NE_E" , 0, 4 },
- [INSTR_NE_FNC] = { "NE_FNC" , 0, 6 },
- [INSTR_LE] = { "LE" , 0, 2 },
- [INSTR_GE] = { "GE" , 0, 2 },
- [INSTR_LT] = { "LT" , 0, 2 },
- [INSTR_GT] = { "GT" , 0, 2 },
- [INSTR_LOAD_F] = { "FIELD_F" , 0, 7 },
- [INSTR_LOAD_V] = { "FIELD_V" , 0, 7 },
- [INSTR_LOAD_S] = { "FIELD_S" , 0, 7 },
- [INSTR_LOAD_ENT] = { "FIELD_ENT" , 0, 9 },
- [INSTR_LOAD_FLD] = { "FIELD_FLD" , 0, 9 },
- [INSTR_LOAD_FNC] = { "FIELD_FNC" , 0, 9 },
- [INSTR_ADDRESS] = { "ADDRESS" , 0, 7 },
- [INSTR_STORE_F] = { "STORE_F" , 0, 7 },
- [INSTR_STORE_V] = { "STORE_V" , 0, 7 },
- [INSTR_STORE_S] = { "STORE_S" , 0, 7 },
- [INSTR_STORE_ENT] = { "STORE_ENT" , 0, 9 },
- [INSTR_STORE_FLD] = { "STORE_FLD" , 0, 9 },
- [INSTR_STORE_FNC] = { "STORE_FNC" , 0, 9 },
- [INSTR_STOREP_F] = { "STOREP_F" , 0, 8 },
- [INSTR_STOREP_V] = { "STOREP_V" , 0, 8 },
- [INSTR_STOREP_S] = { "STOREP_S" , 0, 8 },
- [INSTR_STOREP_ENT] = { "STOREP_ENT", 0, 10},
- [INSTR_STOREP_FLD] = { "STOREP_FLD", 0, 10},
- [INSTR_STOREP_FNC] = { "STOREP_FNC", 0, 10},
- [INSTR_RETURN] = { "RETURN" , 0, 6 },
- [INSTR_NOT_F] = { "NOT_F" , 0, 5 },
- [INSTR_NOT_V] = { "NOT_V" , 0, 5 },
- [INSTR_NOT_S] = { "NOT_S" , 0, 5 },
- [INSTR_NOT_ENT] = { "NOT_ENT" , 0, 7 },
- [INSTR_NOT_FNC] = { "NOT_FNC" , 0, 7 },
- [INSTR_IF] = { "IF" , 0, 2 },
- [INSTR_IFNOT] = { "IFNOT" , 0, 5 },
- [INSTR_CALL0] = { "CALL0" , 0, 5 },
- [INSTR_CALL1] = { "CALL1" , 0, 5 },
- [INSTR_CALL2] = { "CALL2" , 0, 5 },
- [INSTR_CALL3] = { "CALL3" , 0, 5 },
- [INSTR_CALL4] = { "CALL4" , 0, 5 },
- [INSTR_CALL5] = { "CALL5" , 0, 5 },
- [INSTR_CALL6] = { "CALL6" , 0, 5 },
- [INSTR_CALL7] = { "CALL7" , 0, 5 },
- [INSTR_CALL8] = { "CALL8" , 0, 5 },
- [INSTR_STATE] = { "STATE" , 0, 5 },
- [INSTR_GOTO] = { "GOTO" , 0, 4 },
- [INSTR_AND] = { "AND" , 0, 3 },
- [INSTR_OR] = { "OR" , 0, 2 },
- [INSTR_BITAND] = { "BITAND" , 0, 6 },
- [INSTR_BITOR] = { "BITOR" , 0, 5 }
+} asm_instr[] = {
+ { "DONE" , 1, 4 },
+ { "MUL_F" , 3, 5 },
+ { "MUL_V" , 3, 5 },
+ { "MUL_FV" , 3, 6 },
+ { "MUL_VF" , 3, 6 },
+ { "DIV" , 0, 3 },
+ { "ADD_F" , 3, 5 },
+ { "ADD_V" , 3, 5 },
+ { "SUB_F" , 3, 5 },
+ { "DUB_V" , 3, 5 },
+ { "EQ_F" , 0, 4 },
+ { "EQ_V" , 0, 4 },
+ { "EQ_S" , 0, 4 },
+ { "EQ_E" , 0, 4 },
+ { "ES_FNC" , 0, 6 },
+ { "NE_F" , 0, 4 },
+ { "NE_V" , 0, 4 },
+ { "NE_S" , 0, 4 },
+ { "NE_E" , 0, 4 },
+ { "NE_FNC" , 0, 6 },
+ { "LE" , 0, 2 },
+ { "GE" , 0, 2 },
+ { "LT" , 0, 2 },
+ { "GT" , 0, 2 },
+ { "FIELD_F" , 0, 7 },
+ { "FIELD_V" , 0, 7 },
+ { "FIELD_S" , 0, 7 },
+ { "FIELD_ENT" , 0, 9 },
+ { "FIELD_FLD" , 0, 9 },
+ { "FIELD_FNC" , 0, 9 },
+ { "ADDRESS" , 0, 7 },
+ { "STORE_F" , 0, 7 },
+ { "STORE_V" , 0, 7 },
+ { "STORE_S" , 0, 7 },
+ { "STORE_ENT" , 0, 9 },
+ { "STORE_FLD" , 0, 9 },
+ { "STORE_FNC" , 0, 9 },
+ { "STOREP_F" , 0, 8 },
+ { "STOREP_V" , 0, 8 },
+ { "STOREP_S" , 0, 8 },
+ { "STOREP_ENT", 0, 10},
+ { "STOREP_FLD", 0, 10},
+ { "STOREP_FNC", 0, 10},
+ { "RETURN" , 0, 6 },
+ { "NOT_F" , 0, 5 },
+ { "NOT_V" , 0, 5 },
+ { "NOT_S" , 0, 5 },
+ { "NOT_ENT" , 0, 7 },
+ { "NOT_FNC" , 0, 7 },
+ { "IF" , 0, 2 },
+ { "IFNOT" , 0, 5 },
+ { "CALL0" , 0, 5 },
+ { "CALL1" , 0, 5 },
+ { "CALL2" , 0, 5 },
+ { "CALL3" , 0, 5 },
+ { "CALL4" , 0, 5 },
+ { "CALL5" , 0, 5 },
+ { "CALL6" , 0, 5 },
+ { "CALL7" , 0, 5 },
+ { "CALL8" , 0, 5 },
+ { "STATE" , 0, 5 },
+ { "GOTO" , 0, 4 },
+ { "AND" , 0, 3 },
+ { "OR" , 0, 2 },
+ { "BITAND" , 0, 6 },
+ { "BITOR" , 0, 5 }
};
void asm_init (const char *, FILE **);
void asm_close(FILE *);
void asm_parse(FILE *);
-//======================================================================
-//============================= main.c =================================
-//======================================================================
+/*===================================================================*/
+/*============================= main.c ==============================*/
+/*===================================================================*/
enum {
COMPILER_QCC, /* circa QuakeC */
COMPILER_FTEQCC, /* fteqcc QuakeC */
extern bool opts_darkplaces_stringtablebug;
extern bool opts_omit_nullcode;
extern int opts_compiler;
-//======================================================================
-//============================= ast.c ==================================
-//======================================================================
+/*===================================================================*/
+/*============================= ast.c ===============================*/
+/*===================================================================*/
#define MEM_VECTOR_PROTO(Towner, Tmem, mem) \
bool GMQCC_WARN Towner##_##mem##_add(Towner*, Tmem); \
bool GMQCC_WARN Towner##_##mem##_remove(Towner*, size_t)
enum store_types {
store_global,
store_local, /* local, assignable for now, should get promoted later */
- store_value, /* unassignable */
+ store_value /* unassignable */
};
typedef struct {
}
/* nothing found? append */
if (i == self->life_count) {
+ ir_life_entry_t e;
if (life && life->end+1 == s)
{
/* previous life range can be merged in */
}
if (life && life->end >= s)
return false;
- ir_life_entry_t e;
e.start = e.end = s;
if (!ir_value_life_add(self, e))
return false; /* failing */
return false;
}
self->final = true;
- //in = ir_instr_new(self, (v->vtype == TYPE_STRING ? INSTR_IF_S : INSTR_IF_F));
+ /*in = ir_instr_new(self, (v->vtype == TYPE_STRING ? INSTR_IF_S : INSTR_IF_F));*/
in = ir_instr_new(self, VINSTR_COND);
if (!in)
return false;
const char *label, int opcode,
ir_value *left, ir_value *right)
{
+ ir_value *out = NULL;
+ ir_instr *in = NULL;
+
int ot = TYPE_VOID;
switch (opcode) {
case INSTR_ADD_F:
break;
#endif
default:
- // ranges:
+ /* ranges: */
/* boolean operations result in floats */
if (opcode >= INSTR_EQ_F && opcode <= INSTR_GT)
ot = TYPE_FLOAT;
return NULL;
}
- ir_value *out = ir_value_out(self->owner, label, store_local, ot);
+ out = ir_value_out(self->owner, label, store_local, ot);
if (!out)
return NULL;
- ir_instr *in = ir_instr_new(self, opcode);
+ in = ir_instr_new(self, opcode);
if (!in) {
ir_value_delete(out);
return NULL;
}
/* (A) */
tempbool = ir_block_living_add_instr(self, instr->eid);
- //fprintf(stderr, "living added values\n");
+ /*fprintf(stderr, "living added values\n");*/
*changed = *changed || tempbool;
/* new reads: */
if (file->current == sizeof(file->lastok)-1)
file->lastok[file->current] = (char)'\0';
}
-static inline void lex_clear(lex_file *file) {
+static GMQCC_INLINE void lex_clear(lex_file *file) {
file->current = 0;
}
* recrusion.
*/
lex_file *lex_include(lex_file *lex, const char *file) {
+ lex_file *set = NULL;
+
util_strrq(file);
if (strncmp(lex->name, file, strlen(lex->name)) == 0) {
error(lex, ERROR_LEX, "Source file cannot include itself\n");
exit (-1);
}
-
- lex_file *set = NULL;
lex_init(file, &set);
return set;
* SOFTWARE.
*/
#include "gmqcc.h"
-// todo CLEANUP this argitem thing
typedef struct { char *name, type; } argitem;
VECTOR_MAKE(argitem, items);
" %s -c<file> -i<file> -oprog.dat -- compile together (allowed multiple -i<file>)\n"
" %s -a<file> -i<file> -oprog.dat -- assemble together(allowed multiple -i<file>)\n"
" example:\n"
- " %s -cfoo.qc -ibar.qc -oqc.dat -afoo.qs -ibar.qs -oqs.dat\n"
- " additional flags:\n"
+ " %s -cfoo.qc -ibar.qc -oqc.dat -afoo.qs -ibar.qs -oqs.dat\n", app, app, app, app, app);
+
+ printf(" additional flags:\n"
" -debug -- turns on compiler debug messages\n"
" -memchk -- turns on compiler memory leak check\n"
" -help -- prints this help/usage text\n"
- " -std -- select the QuakeC compile type (types below):\n"
- " -std=qcc -- original QuakeC\n"
+ " -std -- select the QuakeC compile type (types below):\n");
+
+ printf(" -std=qcc -- original QuakeC\n"
" -std=ftqecc -- fteqcc QuakeC\n"
" -std=qccx -- qccx QuakeC\n"
- " -std=gmqcc -- this compiler QuakeC (default selection)\n"
- " codegen flags:\n"
+ " -std=gmqcc -- this compiler QuakeC (default selection)\n");
+
+ printf(" codegen flags:\n"
" -fdarkplaces-string-table-bug -- patches the string table to work with bugged versions of darkplaces\n"
- " -fomit-nullcode -- omits the generation of null code (will break everywhere see propsal.txt)\n",
- app,app,app,app,app
- );
+ " -fomit-nullcode -- omits the generation of null code (will break everywhere see propsal.txt)\n");
return -1;
}
return 0;
}
#define param_argument(argtype) do { \
+ argitem item; \
if (argv[1][2]) { \
- items_add((argitem){util_strdup(&argv[1][2]), argtype}); \
+ item.name = util_strdup(&argv[1][2]); \
+ item.type = argtype; \
+ items_add(item); \
} else { \
++argv; \
--argc; \
if (argc <= 1) \
goto clean_params_usage; \
- items_add((argitem){util_strdup(&argv[1][0]), argtype}); \
- } \
+ item.name = util_strdup(argv[1]); \
+ item.type = argtype; \
+ items_add(item); \
+ } \
} while (0)
- case 'c': param_argument(0); break; /* compile */
- case 'a': param_argument(1); break; /* assemble */
- case 'i': param_argument(2); break; /* includes */
+ case 'c': { param_argument(0); break; } /* compile */
+ case 'a': { param_argument(1); break; } /* assemble */
+ case 'i': { param_argument(2); break; } /* includes */
#undef parm_argument
default:
if (!strncmp(&argv[1][1], "debug" , 5)) { opts_debug = true; break; }
switch (items_data[itr].type) {
case 0:
lex_init (items_data[itr].name, &lex);
- lex_parse(lex);
- lex_close(lex);
+ if (lex) {
+ lex_parse(lex);
+ lex_close(lex);
+ }
break;
case 1:
asm_init (items_data[itr].name, &fpp);
- asm_parse(fpp);
- asm_close(fpp);
+ if (fpp) {
+ asm_parse(fpp);
+ asm_close(fpp);
+ }
break;
}
}
util_meminfo();
return 0;
+
clean_params_usage:
for (itr = 0; itr < items_elements; itr++)
mem_d(items_data[itr].name);
case TOKEN_ENTITY: goto fall;
case TOKEN_FLOAT: goto fall;
{
- fall:;
+ fall:; {
char *name = NULL;
int type = token; /* story copy */
if (*file->lastok != '"')
error(file, ERROR_PARSE, "Expected a '\"' (quote) for string constant\n");
/* add the compile-time constant */
- compile_constants_add((constant){
- .name = util_strdup(name),
- .type = TYPE_STRING,
- .value = {0,0,0},
- .string = util_strdup(file->lastok)
- });
+ {
+ constant c;
+ c.name = util_strdup(name),
+ c.type = TYPE_STRING,
+ c.value[0] = 0;
+ c.value[1] = 0;
+ c.value[2] = 0;
+ c.string = util_strdup(file->lastok);
+ compile_constants_add(c);
+ }
break;
/* TODO: name constant, old qc vec literals, whitespace fixes, name constant */
case TOKEN_VECTOR: {
error(file, ERROR_PARSE, "Expected `;` on end of constant initialization for vector\n");
/* add the compile-time constant */
- compile_constants_add((constant){
- .name = util_strdup(name),
- .type = TYPE_VECTOR,
- .value = {
- [0] = compile_calc_x,
- [1] = compile_calc_y,
- [2] = compile_calc_z
- },
- .string = NULL
- });
+ {
+ constant c;
+
+ c.name = util_strdup(name),
+ c.type = TYPE_VECTOR,
+ c.value[0] = compile_calc_x;
+ c.value[1] = compile_calc_y;
+ c.value[2] = compile_calc_z;
+ c.string = NULL;
+ compile_constants_add(c);
+ }
break;
}
case TOKEN_FLOAT: /*TODO: validate, constant generation, name constant */
if (!isdigit(token))
error(file, ERROR_PARSE, "Expected numeric constant for float constant\n");
- compile_constants_add((constant){
- .name = util_strdup(name),
- .type = TOKEN_FLOAT,
- .value = {0,0,0},
- .string = NULL
- });
+ /* constant */
+ {
+ constant c;
+ c.name = util_strdup(name),
+ c.type = TOKEN_FLOAT,
+ c.value[0] = 0;
+ c.value[1] = 0;
+ c.value[2] = 0;
+ c.string = NULL;
+ compile_constants_add(c);
+ }
break;
}
} else if (token == '(') {
printf("FUNCTION ??\n");
}
mem_d(name);
- }
+ }}
/*
* From here down is all language punctuation: There is no
* directives so far are #include.
*/
if (strncmp(file->lastok, "include", sizeof("include")) == 0) {
+ char *copy = NULL;
+ lex_file *next = NULL;
/*
* We only suport include " ", not <> like in C (why?)
* because the latter is silly.
if (token == '\n')
return error(file, ERROR_PARSE, "Invalid use of include preprocessor directive: wanted #include \"file.h\"\n");
- char *copy = util_strdup(file->lastok);
- lex_file *next = lex_include(file, copy);
+ copy = util_strdup(file->lastok);
+ next = lex_include(file, copy);
if (!next) {
error(file, ERROR_INTERNAL, "Include subsystem failure\n");
exit (-1);
}
- compile_constants_add((constant) {
- .name = "#include",
- .type = TYPE_VOID,
- .value = {0,0,0},
- .string = copy
- });
+ /* constant */
+ {
+ constant c;
+ c.name = "#include",
+ c.type = TYPE_VOID,
+ c.value[0] = 0;
+ c.value[1] = 0;
+ c.value[2] = 0;
+ c.string = copy;
+ compile_constants_add(c);
+ }
parse_gen(next);
mem_d (copy);
lex_close(next);
lex_reset(file);
/* free constants */
{
- size_t i = 0;
- for (; i < compile_constants_elements; i++) {
- mem_d(compile_constants_data[i].name);
- mem_d(compile_constants_data[i].string);
- }
- mem_d(compile_constants_data);
- }
+ size_t i = 0;
+ for (; i < compile_constants_elements; i++) {
+ mem_d(compile_constants_data[i].name);
+ mem_d(compile_constants_data[i].string);
+ }
+ mem_d(compile_constants_data);
+ }
return 1;
}
#include <errno.h>
#include "gmqcc.h"
-unsigned long long mem_ab = 0;
-unsigned long long mem_db = 0;
-unsigned long long mem_at = 0;
-unsigned long long mem_dt = 0;
+uint64_t mem_ab = 0;
+uint64_t mem_db = 0;
+uint64_t mem_at = 0;
+uint64_t mem_dt = 0;
struct memblock_t {
const char *file;
}
void util_memory_d(void *ptrn, unsigned int line, const char *file) {
+ void *data = NULL;
+ struct memblock_t *info = NULL;
if (!ptrn) return;
- void *data = (void*)((uintptr_t)ptrn-sizeof(struct memblock_t));
- struct memblock_t *info = (struct memblock_t*)data;
-
+ data = (void*)((uintptr_t)ptrn-sizeof(struct memblock_t));
+ info = (struct memblock_t*)data;
+
util_debug("MEM", "released: % 8u (bytes) address 0x%08X @ %s:%u\n", info->byte, data, file, line);
mem_db += info->byte;
mem_dt++;
* copy of it and null terminating it at the required position.
*/
char *util_strchp(const char *s, const char *e) {
+ const char *c = NULL;
if (!s || !e)
return NULL;
- const char *c = s;
+ c = s;
while (c != e)
c++;
* access.
*/
char *util_strrnl(const char *src) {
- if (!src) return NULL;
- char *cpy = (char*)src;
- while (*cpy && *cpy != '\n')
- cpy++;
+ char *cpy = NULL;
+
+ if (src) {
+ cpy = (char*)src;
+ while (*cpy && *cpy != '\n')
+ cpy++;
- *cpy = '\0';
+ *cpy = '\0';
+ }
return (char*)src;
}
}
void util_debug(const char *area, const char *ms, ...) {
+ va_list va;
if (!opts_debug)
return;
- va_list va;
va_start(va, ms);
fprintf (stdout, "DEBUG: ");
fputc ('[', stdout);