All code is now C89/C90 compat

This commit is contained in:
Dale Weiler 2012-04-28 18:56:09 -04:00
parent 206952b920
commit 3e7a8c0e78
10 changed files with 361 additions and 263 deletions

View file

@ -1,5 +1,5 @@
CC ?= clang
CFLAGS += -Wall -pedantic-errors -std=c99
CFLAGS += -Wall -pedantic-errors -std=c90
OBJ = main.o \
lex.o \
error.o \

38
asm.c
View file

@ -77,7 +77,7 @@ void asm_clear() {
* 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]) &&
@ -141,7 +141,7 @@ static inline bool asm_parse_type(const char *skip, size_t line, asm_state *stat
* 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;
@ -169,6 +169,9 @@ static inline bool asm_parse_func(const char *skip, size_t line, asm_state *stat
* to determine this.
*/
if (strchr(name, ',')) {
prog_section_function function;
prog_section_def def;
char *find = strchr(name, ',') + 1;
/* skip whitespace */
@ -197,21 +200,20 @@ static inline bool asm_parse_func(const char *skip, size_t line, asm_state *stat
* 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
@ -225,7 +227,7 @@ static inline bool asm_parse_func(const char *skip, size_t line, asm_state *stat
printf("invalid internal function identifier, must be all numeric\n");
} else {
/* TODO: function bodies */
printf("Found function %s\n", name);
}
mem_d(copy);

15
ast.c
View file

@ -27,10 +27,10 @@
#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)
@ -180,6 +180,8 @@ void ast_block_delete(ast_block *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)
@ -187,8 +189,6 @@ ast_function* ast_function_new(lex_ctx ctx, const char *name, ast_value *vtype)
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);
@ -241,6 +241,7 @@ bool ast_value_codegen(ast_value *self, ast_function *func, ir_value **out)
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);
@ -252,7 +253,7 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir)
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;

136
code.c
View file

@ -84,6 +84,10 @@ VECTOR_MAKE(int, code_globals );
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;
@ -92,10 +96,7 @@ void code_init() {
* 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');
@ -104,6 +105,19 @@ void code_init() {
}
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);
@ -117,24 +131,30 @@ void code_test() {
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) {
@ -142,14 +162,27 @@ void code_write() {
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) {
@ -162,21 +195,21 @@ void code_write() {
}
/* 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));
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);
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 );
@ -191,22 +224,21 @@ void code_write() {
/* 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 &&

233
gmqcc.h
View file

@ -74,6 +74,25 @@
*/
#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
@ -94,9 +113,15 @@
#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;
@ -109,15 +134,17 @@
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 */
@ -144,11 +171,11 @@ enum {
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 ,
@ -176,9 +203,9 @@ void lex_parse (lex_file *);
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)
@ -186,14 +213,14 @@ void lex_init (const char *, lex_file **);
#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;
@ -204,9 +231,9 @@ typedef_node *typedef_find(const char *);
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 ();
@ -242,14 +269,14 @@ uint32_t util_crc32(const char *, int, register const short);
/* 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; \
} \
@ -272,9 +299,9 @@ uint32_t util_crc32(const char *, int, register const short);
VECTOR_TYPE(T,N); \
VECTOR_CORE(T,N)
//===================================================================
//=========================== code.c ================================
//===================================================================
/*===================================================================*/
/*=========================== code.c ================================*/
/*===================================================================*/
enum {
TYPE_VOID ,
TYPE_STRING ,
@ -285,7 +312,7 @@ enum {
TYPE_FUNCTION ,
TYPE_POINTER ,
/* TYPE_INTEGER , */
TYPE_VARIANT ,
TYPE_VARIANT
};
/*
@ -441,7 +468,7 @@ enum {
*/
VINSTR_PHI,
VINSTR_JUMP,
VINSTR_COND,
VINSTR_COND
};
/*
@ -481,88 +508,88 @@ extern long code_defs_elements;
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 */
@ -574,9 +601,9 @@ extern bool opts_memchk;
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)
@ -690,7 +717,7 @@ _MEM_VEC_FUN_FIND(Tself, Twhat, mem)
enum store_types {
store_global,
store_local, /* local, assignable for now, should get promoted later */
store_value, /* unassignable */
store_value /* unassignable */
};
typedef struct {

15
ir.c
View file

@ -511,6 +511,7 @@ bool ir_value_life_merge(ir_value *self, size_t s)
}
/* 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 */
@ -519,7 +520,6 @@ bool ir_value_life_merge(ir_value *self, size_t s)
}
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 */
@ -657,7 +657,7 @@ bool ir_block_create_if(ir_block *self, ir_value *v,
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;
@ -786,6 +786,9 @@ ir_value* ir_block_create_binop(ir_block *self,
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:
@ -854,7 +857,7 @@ ir_value* ir_block_create_binop(ir_block *self,
break;
#endif
default:
// ranges:
/* ranges: */
/* boolean operations result in floats */
if (opcode >= INSTR_EQ_F && opcode <= INSTR_GT)
ot = TYPE_FLOAT;
@ -871,11 +874,11 @@ ir_value* ir_block_create_binop(ir_block *self,
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;
@ -1433,7 +1436,7 @@ static bool ir_block_life_propagate(ir_block *self, ir_block *prev, bool *change
}
/* (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: */

6
lex.c
View file

@ -67,7 +67,7 @@ static void lex_addch(int ch, lex_file *file) {
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;
}
@ -342,13 +342,13 @@ void lex_parse(lex_file *file) {
* 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;

50
main.c
View file

@ -21,7 +21,6 @@
* SOFTWARE.
*/
#include "gmqcc.h"
// todo CLEANUP this argitem thing
typedef struct { char *name, type; } argitem;
VECTOR_MAKE(argitem, items);
@ -39,21 +38,22 @@ static const int usage(const char *const app) {
" %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;
}
@ -87,20 +87,25 @@ int main(int argc, char **argv) {
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; }
@ -152,13 +157,17 @@ int main(int argc, char **argv) {
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;
}
}
@ -171,6 +180,7 @@ int main(int argc, char **argv) {
util_meminfo();
return 0;
clean_params_usage:
for (itr = 0; itr < items_elements; itr++)
mem_d(items_data[itr].name);

95
parse.c
View file

@ -82,7 +82,7 @@ int parse_gen(lex_file *file) {
case TOKEN_ENTITY: goto fall;
case TOKEN_FLOAT: goto fall;
{
fall:;
fall:; {
char *name = NULL;
int type = token; /* story copy */
@ -119,12 +119,16 @@ int parse_gen(lex_file *file) {
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: {
@ -206,16 +210,17 @@ int parse_gen(lex_file *file) {
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;
}
@ -223,19 +228,24 @@ int parse_gen(lex_file *file) {
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
@ -253,6 +263,8 @@ int parse_gen(lex_file *file) {
* 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.
@ -262,19 +274,24 @@ int parse_gen(lex_file *file) {
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);
@ -293,12 +310,12 @@ int parse_gen(lex_file *file) {
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;
}

34
util.c
View file

@ -24,10 +24,10 @@
#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;
@ -51,10 +51,12 @@ void *util_memory_a(unsigned int byte, unsigned int line, 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++;
@ -124,10 +126,11 @@ char *util_strrq(const char *s) {
* 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++;
@ -140,12 +143,15 @@ char *util_strchp(const char *s, const char *e) {
* access.
*/
char *util_strrnl(const char *src) {
if (!src) return NULL;
char *cpy = (char*)src;
while (*cpy && *cpy != '\n')
cpy++;
char *cpy = NULL;
*cpy = '\0';
if (src) {
cpy = (char*)src;
while (*cpy && *cpy != '\n')
cpy++;
*cpy = '\0';
}
return (char*)src;
}
@ -191,10 +197,10 @@ bool util_strdigit(const char *str) {
}
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);