Replaced it all...

This commit is contained in:
Wolfgang (Blub) Bumiller 2012-11-15 18:32:03 +01:00
parent b8fc2b7731
commit 906f319673
11 changed files with 933 additions and 1320 deletions

144
ast.c
View file

@ -70,7 +70,7 @@ static void ast_expression_init(ast_expression *self,
self->expression.outl = NULL;
self->expression.outr = NULL;
self->expression.variadic = false;
MEM_VECTOR_INIT(&self->expression, params);
self->expression.params = NULL;
}
static void ast_expression_delete(ast_expression *self)
@ -78,10 +78,10 @@ static void ast_expression_delete(ast_expression *self)
size_t i;
if (self->expression.next)
ast_delete(self->expression.next);
for (i = 0; i < self->expression.params_count; ++i) {
for (i = 0; i < vec_size(self->expression.params); ++i) {
ast_delete(self->expression.params[i]);
}
MEM_VECTOR_CLEAR(&self->expression, params);
vec_free(self->expression.params);
}
static void ast_expression_delete_full(ast_expression *self)
@ -90,8 +90,6 @@ static void ast_expression_delete_full(ast_expression *self)
mem_d(self);
}
MEM_VEC_FUNCTIONS(ast_expression_common, ast_value*, params)
ast_value* ast_value_copy(const ast_value *self)
{
size_t i;
@ -108,12 +106,13 @@ ast_value* ast_value_copy(const ast_value *self)
fromex = &self->expression;
selfex = &cp->expression;
selfex->variadic = fromex->variadic;
for (i = 0; i < fromex->params_count; ++i) {
for (i = 0; i < vec_size(fromex->params); ++i) {
ast_value *v = ast_value_copy(fromex->params[i]);
if (!v || !ast_expression_common_params_add(selfex, v)) {
if (!v) {
ast_value_delete(cp);
return NULL;
}
vec_push(selfex->params, v);
}
return cp;
}
@ -132,10 +131,11 @@ bool ast_type_adopt_impl(ast_expression *self, const ast_expression *other)
fromex = &other->expression;
selfex = &self->expression;
selfex->variadic = fromex->variadic;
for (i = 0; i < fromex->params_count; ++i) {
for (i = 0; i < vec_size(fromex->params); ++i) {
ast_value *v = ast_value_copy(fromex->params[i]);
if (!v || !ast_expression_common_params_add(selfex, v))
if (!v)
return false;
vec_push(selfex->params, v);
}
return true;
}
@ -182,12 +182,13 @@ ast_expression* ast_type_copy(lex_ctx ctx, const ast_expression *ex)
selfex->next = NULL;
selfex->variadic = fromex->variadic;
for (i = 0; i < fromex->params_count; ++i) {
for (i = 0; i < vec_size(fromex->params); ++i) {
ast_value *v = ast_value_copy(fromex->params[i]);
if (!v || !ast_expression_common_params_add(selfex, v)) {
if (!v) {
ast_expression_delete_full(self);
return NULL;
}
vec_push(selfex->params, v);
}
return self;
@ -200,13 +201,13 @@ bool ast_compare_type(ast_expression *a, ast_expression *b)
return false;
if (!a->expression.next != !b->expression.next)
return false;
if (a->expression.params_count != b->expression.params_count)
if (vec_size(a->expression.params) != vec_size(b->expression.params))
return false;
if (a->expression.variadic != b->expression.variadic)
return false;
if (a->expression.params_count) {
if (vec_size(a->expression.params)) {
size_t i;
for (i = 0; i < a->expression.params_count; ++i) {
for (i = 0; i < vec_size(a->expression.params); ++i) {
if (!ast_compare_type((ast_expression*)a->expression.params[i],
(ast_expression*)b->expression.params[i]))
return false;
@ -257,14 +258,14 @@ static size_t ast_type_to_string_impl(ast_expression *e, char *buf, size_t bufsi
pos = ast_type_to_string_impl(e->expression.next, buf, bufsize, pos);
if (pos + 2 >= bufsize)
goto full;
if (e->expression.params_count == 0) {
if (!vec_size(e->expression.params)) {
buf[pos++] = '(';
buf[pos++] = ')';
return pos;
}
buf[pos++] = '(';
pos = ast_type_to_string_impl((ast_expression*)(e->expression.params[0]), buf, bufsize, pos);
for (i = 1; i < e->expression.params_count; ++i) {
for (i = 1; i < vec_size(e->expression.params); ++i) {
if (pos + 2 >= bufsize)
goto full;
buf[pos++] = ',';
@ -360,9 +361,9 @@ void ast_value_delete(ast_value* self)
mem_d(self);
}
bool GMQCC_WARN ast_value_params_add(ast_value *self, ast_value *p)
void ast_value_params_add(ast_value *self, ast_value *p)
{
return ast_expression_common_params_add(&self->expression, p);
vec_push(self->expression.params, p);
}
bool ast_value_set_name(ast_value *self, const char *name)
@ -705,8 +706,7 @@ ast_call* ast_call_new(lex_ctx ctx,
ast_instantiate(ast_call, ctx, ast_call_delete);
ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_call_codegen);
MEM_VECTOR_INIT(self, params);
self->params = NULL;
self->func = funcexpr;
self->expression.vtype = funcexpr->expression.next->expression.vtype;
@ -715,14 +715,13 @@ ast_call* ast_call_new(lex_ctx ctx,
return self;
}
MEM_VEC_FUNCTIONS(ast_call, ast_expression*, params)
void ast_call_delete(ast_call *self)
{
size_t i;
for (i = 0; i < self->params_count; ++i)
for (i = 0; i < vec_size(self->params); ++i)
ast_unref(self->params[i]);
MEM_VECTOR_CLEAR(self, params);
vec_free(self->params);
if (self->func)
ast_unref(self->func);
@ -736,9 +735,9 @@ bool ast_call_check_types(ast_call *self)
size_t i;
bool retval = true;
const ast_expression *func = self->func;
size_t count = self->params_count;
if (count > func->expression.params_count)
count = func->expression.params_count;
size_t count = vec_size(self->params);
if (count > vec_size(func->expression.params))
count = vec_size(func->expression.params);
for (i = 0; i < count; ++i) {
if (!ast_compare_type(self->params[i], (ast_expression*)(func->expression.params[i]))) {
@ -789,36 +788,31 @@ ast_block* ast_block_new(lex_ctx ctx)
ast_expression_init((ast_expression*)self,
(ast_expression_codegen*)&ast_block_codegen);
MEM_VECTOR_INIT(self, locals);
MEM_VECTOR_INIT(self, exprs);
MEM_VECTOR_INIT(self, collect);
self->locals = NULL;
self->exprs = NULL;
self->collect = NULL;
return self;
}
MEM_VEC_FUNCTIONS(ast_block, ast_value*, locals)
MEM_VEC_FUNCTIONS(ast_block, ast_expression*, exprs)
MEM_VEC_FUNCTIONS(ast_block, ast_expression*, collect)
bool ast_block_collect(ast_block *self, ast_expression *expr)
void ast_block_collect(ast_block *self, ast_expression *expr)
{
if (!ast_block_collect_add(self, expr))
return false;
vec_push(self->collect, expr);
expr->expression.node.keep = true;
return true;
}
void ast_block_delete(ast_block *self)
{
size_t i;
for (i = 0; i < self->exprs_count; ++i)
for (i = 0; i < vec_size(self->exprs); ++i)
ast_unref(self->exprs[i]);
MEM_VECTOR_CLEAR(self, exprs);
for (i = 0; i < self->locals_count; ++i)
vec_free(self->exprs);
for (i = 0; i < vec_size(self->locals); ++i)
ast_delete(self->locals[i]);
MEM_VECTOR_CLEAR(self, locals);
for (i = 0; i < self->collect_count; ++i)
vec_free(self->exprs);
for (i = 0; i < vec_size(self->collect); ++i)
ast_delete(self->collect[i]);
MEM_VECTOR_CLEAR(self, collect);
vec_free(self->exprs);
ast_expression_delete((ast_expression*)self);
mem_d(self);
}
@ -852,7 +846,7 @@ ast_function* ast_function_new(lex_ctx ctx, const char *name, ast_value *vtype)
self->vtype = vtype;
self->name = name ? util_strdup(name) : NULL;
MEM_VECTOR_INIT(self, blocks);
self->blocks = NULL;
self->labelcount = 0;
self->builtin = 0;
@ -869,8 +863,6 @@ ast_function* ast_function_new(lex_ctx ctx, const char *name, ast_value *vtype)
return self;
}
MEM_VEC_FUNCTIONS(ast_function, ast_block*, blocks)
void ast_function_delete(ast_function *self)
{
size_t i;
@ -885,9 +877,9 @@ void ast_function_delete(ast_function *self)
*/
ast_unref(self->vtype);
}
for (i = 0; i < self->blocks_count; ++i)
for (i = 0; i < vec_size(self->blocks); ++i)
ast_delete(self->blocks[i]);
MEM_VECTOR_CLEAR(self, blocks);
vec_free(self->blocks);
mem_d(self);
}
@ -1255,10 +1247,9 @@ bool ast_function_codegen(ast_function *self, ir_builder *ir)
/* fill the parameter list */
ec = &self->vtype->expression;
for (i = 0; i < ec->params_count; ++i)
for (i = 0; i < vec_size(ec->params); ++i)
{
if (!ir_function_params_add(irf, ec->params[i]->expression.vtype))
return false;
vec_push(irf->params, ec->params[i]->expression.vtype);
if (!self->builtin) {
if (!ast_local_codegen(ec->params[i], self->ir_func, true))
return false;
@ -1270,7 +1261,7 @@ bool ast_function_codegen(ast_function *self, ir_builder *ir)
return true;
}
if (!self->blocks_count) {
if (!vec_size(self->blocks)) {
asterror(ast_ctx(self), "function `%s` has no body", self->name);
return false;
}
@ -1281,7 +1272,7 @@ bool ast_function_codegen(ast_function *self, ir_builder *ir)
return false;
}
for (i = 0; i < self->blocks_count; ++i) {
for (i = 0; i < vec_size(self->blocks); ++i) {
ast_expression_codegen *gen = self->blocks[i]->expression.codegen;
if (!(*gen)((ast_expression*)self->blocks[i], self, false, &dummy))
return false;
@ -1342,7 +1333,7 @@ bool ast_block_codegen(ast_block *self, ast_function *func, bool lvalue, ir_valu
*out = NULL;
/* generate locals */
for (i = 0; i < self->locals_count; ++i)
for (i = 0; i < vec_size(self->locals); ++i)
{
if (!ast_local_codegen(self->locals[i], func->ir_func, false)) {
if (opts_debug)
@ -1351,7 +1342,7 @@ bool ast_block_codegen(ast_block *self, ast_function *func, bool lvalue, ir_valu
}
}
for (i = 0; i < self->exprs_count; ++i)
for (i = 0; i < vec_size(self->exprs); ++i)
{
ast_expression_codegen *gen = self->exprs[i]->expression.codegen;
if (!(*gen)(self->exprs[i], func, false, out))
@ -1423,10 +1414,8 @@ bool ast_store_codegen(ast_store *self, ast_function *func, bool lvalue, ir_valu
call = ir_block_create_call(func->curblock, ast_function_label(func, "store"), funval);
if (!call)
return false;
if (!ir_call_param(call, iridx))
return false;
if (!ir_call_param(call, right))
return false;
ir_call_param(call, iridx);
ir_call_param(call, right);
self->expression.outr = right;
}
else
@ -1747,8 +1736,7 @@ bool ast_array_index_codegen(ast_array_index *self, ast_function *func, bool lva
call = ir_block_create_call(func->curblock, ast_function_label(func, "fetch"), funval);
if (!call)
return false;
if (!ir_call_param(call, iridx))
return false;
ir_call_param(call, iridx);
*out = ir_call_value(call);
self->expression.outr = *out;
@ -1955,12 +1943,10 @@ bool ast_ternary_codegen(ast_ternary *self, ast_function *func, bool lvalue, ir_
/* create PHI */
phi = ir_block_create_phi(merge, ast_function_label(func, "phi"), trueval->vtype);
if (!phi ||
!ir_phi_add(phi, ontrue, trueval) ||
!ir_phi_add(phi, onfalse, falseval))
{
if (!phi)
return false;
}
ir_phi_add(phi, ontrue, trueval);
ir_phi_add(phi, onfalse, falseval);
self->phi_out = ir_phi_value(phi);
*out = self->phi_out;
@ -2072,7 +2058,7 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value
bpostcond = end_bpostcond = NULL;
}
bout_id = func->ir_func->blocks_count;
bout_id = vec_size(func->ir_func->blocks);
bout = ir_function_create_block(func->ir_func, ast_function_label(func, "after_loop"));
if (!bout)
return false;
@ -2192,12 +2178,8 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value
}
/* Move 'bout' to the end */
if (!ir_function_blocks_remove(func->ir_func, bout_id) ||
!ir_function_blocks_add(func->ir_func, bout))
{
ir_block_delete(bout);
return false;
}
vec_remove(func->ir_func->blocks, bout_id, 1);
vec_push(func->ir_func->blocks, bout);
return true;
}
@ -2205,7 +2187,7 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value
bool ast_call_codegen(ast_call *self, ast_function *func, bool lvalue, ir_value **out)
{
ast_expression_codegen *cgen;
ir_value_vector params;
ir_value **params;
ir_instr *callinstr;
size_t i;
@ -2228,10 +2210,10 @@ bool ast_call_codegen(ast_call *self, ast_function *func, bool lvalue, ir_value
if (!funval)
return false;
MEM_VECTOR_INIT(&params, v);
params = NULL;
/* parameters */
for (i = 0; i < self->params_count; ++i)
for (i = 0; i < vec_size(self->params); ++i)
{
ir_value *param;
ast_expression *expr = self->params[i];
@ -2241,25 +2223,23 @@ bool ast_call_codegen(ast_call *self, ast_function *func, bool lvalue, ir_value
goto error;
if (!param)
goto error;
if (!ir_value_vector_v_add(&params, param))
goto error;
vec_push(params, param);
}
callinstr = ir_block_create_call(func->curblock, ast_function_label(func, "call"), funval);
if (!callinstr)
goto error;
for (i = 0; i < params.v_count; ++i) {
if (!ir_call_param(callinstr, params.v[i]))
goto error;
for (i = 0; i < vec_size(params); ++i) {
ir_call_param(callinstr, params[i]);
}
*out = ir_call_value(callinstr);
self->expression.outr = *out;
MEM_VECTOR_CLEAR(&params, v);
vec_free(params);
return true;
error:
MEM_VECTOR_CLEAR(&params, v);
vec_free(params);
return false;
}

25
ast.h
View file

@ -120,7 +120,7 @@ typedef struct
ast_expression *next;
/* arrays get a member-count */
size_t count;
MEM_VECTOR_MAKE(ast_value*, params);
ast_value* *params;
bool variadic;
/* The codegen functions should store their output values
* so we can call it multiple times without re-evaluating.
@ -130,7 +130,6 @@ typedef struct
ir_value *outl;
ir_value *outr;
} ast_expression_common;
MEM_VECTOR_PROTO(ast_expression_common, ast_value*, params);
/* Value
*
@ -183,7 +182,7 @@ bool ast_value_codegen(ast_value*, ast_function*, bool lvalue, ir_value**);
bool ast_local_codegen(ast_value *self, ir_function *func, bool isparam);
bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield);
bool GMQCC_WARN ast_value_params_add(ast_value*, ast_value*);
void ast_value_params_add(ast_value*, ast_value*);
bool ast_compare_type(ast_expression *a, ast_expression *b);
ast_expression* ast_type_copy(lex_ctx ctx, const ast_expression *ex);
@ -460,7 +459,7 @@ struct ast_call_s
{
ast_expression_common expression;
ast_expression *func;
MEM_VECTOR_MAKE(ast_expression*, params);
ast_expression* *params;
};
ast_call* ast_call_new(lex_ctx ctx,
ast_expression *funcexpr);
@ -468,8 +467,6 @@ void ast_call_delete(ast_call*);
bool ast_call_codegen(ast_call*, ast_function*, bool lvalue, ir_value**);
bool ast_call_check_types(ast_call*);
MEM_VECTOR_PROTO(ast_call, ast_expression*, params);
/* Blocks
*
*/
@ -477,20 +474,16 @@ struct ast_block_s
{
ast_expression_common expression;
MEM_VECTOR_MAKE(ast_value*, locals);
MEM_VECTOR_MAKE(ast_expression*, exprs);
MEM_VECTOR_MAKE(ast_expression*, collect);
ast_value* *locals;
ast_expression* *exprs;
ast_expression* *collect;
};
ast_block* ast_block_new(lex_ctx ctx);
void ast_block_delete(ast_block*);
bool ast_block_set_type(ast_block*, ast_expression *from);
MEM_VECTOR_PROTO(ast_block, ast_value*, locals);
MEM_VECTOR_PROTO(ast_block, ast_expression*, exprs);
MEM_VECTOR_PROTO(ast_block, ast_expression*, collect);
bool ast_block_codegen(ast_block*, ast_function*, bool lvalue, ir_value**);
bool ast_block_collect(ast_block*, ast_expression*);
void ast_block_collect(ast_block*, ast_expression*);
/* Function
*
@ -523,7 +516,7 @@ struct ast_function_s
*/
char labelbuf[64];
MEM_VECTOR_MAKE(ast_block*, blocks);
ast_block* *blocks;
};
ast_function* ast_function_new(lex_ctx ctx, const char *name, ast_value *vtype);
/* This will NOT delete the underlying ast_value */
@ -533,8 +526,6 @@ void ast_function_delete(ast_function*);
*/
const char* ast_function_label(ast_function*, const char *prefix);
MEM_VECTOR_PROTO(ast_function, ast_block*, blocks);
bool ast_function_codegen(ast_function *self, ir_builder *builder);
/* Expression union

224
code.c
View file

@ -22,46 +22,12 @@
*/
#include "gmqcc.h"
/*
* The macros below expand to a typesafe vector implementation, which
* can be viewed in gmqcc.h
*
* code_statements_data -- raw prog_section_statement array
* code_statements_elements -- number of elements
* code_statements_allocated -- size of the array allocated
* code_statements_add(T) -- add element (returns -1 on error)
*
* code_vars_data -- raw prog_section_var array
* code_vars_elements -- number of elements
* code_vars_allocated -- size of the array allocated
* code_vars_add(T) -- add element (returns -1 on error)
*
* code_fields_data -- raw prog_section_field array
* code_fields_elements -- number of elements
* code_fields_allocated -- size of the array allocated
* code_fields_add(T) -- add element (returns -1 on error)
*
* code_functions_data -- raw prog_section_function array
* code_functions_elements -- number of elements
* code_functions_allocated -- size of the array allocated
* code_functions_add(T) -- add element (returns -1 on error)
*
* code_globals_data -- raw prog_section_def array
* code_globals_elements -- number of elements
* code_globals_allocated -- size of the array allocated
* code_globals_add(T) -- add element (returns -1 on error)
*
* code_chars_data -- raw char* array
* code_chars_elements -- number of elements
* code_chars_allocated -- size of the array allocated
* code_chars_add(T) -- add element (returns -1 on error)
*/
VECTOR_MAKE(prog_section_statement, code_statements);
VECTOR_MAKE(prog_section_def, code_defs );
VECTOR_MAKE(prog_section_field, code_fields );
VECTOR_MAKE(prog_section_function, code_functions );
VECTOR_MAKE(int, code_globals );
VECTOR_MAKE(char, code_chars );
prog_section_statement *code_statements;
prog_section_def *code_defs;
prog_section_field *code_fields;
prog_section_function *code_functions;
int *code_globals;
char *code_chars;
uint16_t code_crc;
uint32_t code_entfields;
@ -83,23 +49,23 @@ void code_init() {
* some null (empty) statements, functions, and 28 globals
*/
for(; i < 28; i++)
code_globals_add(0);
vec_push(code_globals, 0);
code_chars_add ('\0');
code_functions_add (empty_function);
code_statements_add(empty_statement);
code_defs_add (empty_def);
code_fields_add (empty_def);
vec_push(code_chars, '\0');
vec_push(code_functions, empty_function);
vec_push(code_statements, empty_statement);
vec_push(code_defs, empty_def);
vec_push(code_fields, empty_def);
}
uint32_t code_genstring(const char *str)
{
uint32_t off = code_chars_elements;
uint32_t off = vec_size(code_chars);
while (*str) {
code_chars_add(*str);
vec_push(code_chars, *str);
++str;
}
code_chars_add(0);
vec_push(code_chars, 0);
return off;
}
@ -110,10 +76,10 @@ uint32_t code_cachedstring(const char *str)
* and also take substrings, but I'm uncomfortable with
* pointing to subparts of strings for the sake of clarity...
*/
while (s < code_chars_elements) {
if (!strcmp(str, code_chars_data + s))
while (s < vec_size(code_chars)) {
if (!strcmp(str, code_chars + s))
return s;
while (code_chars_data[s]) ++s;
while (code_chars[s]) ++s;
++s;
}
return code_genstring(str);
@ -133,31 +99,31 @@ void code_test() {
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_chars_put("m_keydown", 0x9);
code_chars_put("m_draw", 0x6);
code_chars_put("m_toggle", 0x8);
code_chars_put("m_shutdown", 0xA);
strcpy(vec_add(code_chars, 0x7), "m_init");
strcpy(vec_add(code_chars, 0x6), "print");
strcpy(vec_add(code_chars, 0xD), "hello world\n");
strcpy(vec_add(code_chars, 0xA), "m_keydown");
strcpy(vec_add(code_chars, 0x7), "m_draw");
strcpy(vec_add(code_chars, 0x9), "m_toggle");
strcpy(vec_add(code_chars, 0xB), "m_shutdown");
code_globals_add(1); /* m_init */
code_globals_add(2); /* print */
code_globals_add(14); /* hello world in string table */
vec_push(code_globals, 1); /* m_init */
vec_push(code_globals, 2); /* print */
vec_push(code_globals, 14); /* hello world in string table */
/* now the defs */
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);
vec_push(code_defs, d1); /* m_init */
vec_push(code_defs, d2); /* print */
vec_push(code_defs, d3); /*hello_world*/
vec_push(code_functions, f1); /* m_init */
vec_push(code_functions, f2); /* print */
vec_push(code_functions, f3); /* m_keydown */
vec_push(code_functions, f4);
vec_push(code_functions, f5);
vec_push(code_functions, f6);
vec_push(code_statements, s1);
vec_push(code_statements, s2);
vec_push(code_statements, s3);
}
qcint code_alloc_field (size_t qcsize)
@ -175,17 +141,17 @@ bool code_write(const char *filename) {
/* see proposal.txt */
if (OPTS_FLAG(OMIT_NULL_BYTES)) {}
code_header.statements.offset = sizeof(prog_header);
code_header.statements.length = code_statements_elements;
code_header.defs.offset = code_header.statements.offset + (sizeof(prog_section_statement) * code_statements_elements);
code_header.defs.length = code_defs_elements;
code_header.fields.offset = code_header.defs.offset + (sizeof(prog_section_def) * code_defs_elements);
code_header.fields.length = code_fields_elements;
code_header.functions.offset = code_header.fields.offset + (sizeof(prog_section_field) * code_fields_elements);
code_header.functions.length = code_functions_elements;
code_header.globals.offset = code_header.functions.offset + (sizeof(prog_section_function) * code_functions_elements);
code_header.globals.length = code_globals_elements;
code_header.strings.offset = code_header.globals.offset + (sizeof(int32_t) * code_globals_elements);
code_header.strings.length = code_chars_elements;
code_header.statements.length = vec_size(code_statements);
code_header.defs.offset = code_header.statements.offset + (sizeof(prog_section_statement) * vec_size(code_statements));
code_header.defs.length = vec_size(code_defs);
code_header.fields.offset = code_header.defs.offset + (sizeof(prog_section_def) * vec_size(code_defs));
code_header.fields.length = vec_size(code_fields);
code_header.functions.offset = code_header.fields.offset + (sizeof(prog_section_field) * vec_size(code_fields));
code_header.functions.length = vec_size(code_functions);
code_header.globals.offset = code_header.functions.offset + (sizeof(prog_section_function) * vec_size(code_functions));
code_header.globals.length = vec_size(code_globals);
code_header.strings.offset = code_header.globals.offset + (sizeof(int32_t) * vec_size(code_globals));
code_header.strings.length = vec_size(code_chars);
code_header.version = 6;
if (opts_forcecrc)
code_header.crc16 = opts_forced_crc;
@ -197,30 +163,30 @@ bool code_write(const char *filename) {
util_debug("GEN", "Patching stringtable for -fdarkplaces-stringtablebug\n");
/* >= + P */
code_chars_add('\0'); /* > */
code_chars_add('\0'); /* = */
code_chars_add('\0'); /* P */
vec_push(code_chars, '\0'); /* > */
vec_push(code_chars, '\0'); /* = */
vec_push(code_chars, '\0'); /* P */
}
/* 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(int32_t));
util_endianswap(code_statements, vec_size(code_statements), sizeof(prog_section_statement));
util_endianswap(code_defs, vec_size(code_defs), sizeof(prog_section_def));
util_endianswap(code_fields, vec_size(code_fields), sizeof(prog_section_field));
util_endianswap(code_functions, vec_size(code_functions), sizeof(prog_section_function));
util_endianswap(code_globals, vec_size(code_globals), sizeof(int32_t));
fp = util_fopen(filename, "wb");
if (!fp)
return false;
if (1 != fwrite(&code_header, sizeof(prog_header), 1, fp) ||
code_statements_elements != fwrite(code_statements_data, sizeof(prog_section_statement), code_statements_elements, fp) ||
code_defs_elements != fwrite(code_defs_data, sizeof(prog_section_def) , code_defs_elements , fp) ||
code_fields_elements != fwrite(code_fields_data, sizeof(prog_section_field) , code_fields_elements , fp) ||
code_functions_elements != fwrite(code_functions_data, sizeof(prog_section_function) , code_functions_elements , fp) ||
code_globals_elements != fwrite(code_globals_data, sizeof(int32_t) , code_globals_elements , fp) ||
code_chars_elements != fwrite(code_chars_data, 1 , code_chars_elements , fp))
vec_size(code_statements) != fwrite(code_statements, sizeof(prog_section_statement), vec_size(code_statements), fp) ||
vec_size(code_defs) != fwrite(code_defs, sizeof(prog_section_def) , vec_size(code_defs) , fp) ||
vec_size(code_fields) != fwrite(code_fields, sizeof(prog_section_field) , vec_size(code_fields) , fp) ||
vec_size(code_functions) != fwrite(code_functions, sizeof(prog_section_function) , vec_size(code_functions) , fp) ||
vec_size(code_globals) != fwrite(code_globals, sizeof(int32_t) , vec_size(code_globals) , fp) ||
vec_size(code_chars) != fwrite(code_chars, 1 , vec_size(code_chars) , fp))
{
fclose(fp);
return false;
@ -239,37 +205,37 @@ bool code_write(const char *filename) {
/* FUNCTIONS */
util_debug("GEN", "FUNCTIONS:\n");
for (; it < code_functions_elements; it++) {
size_t j = code_functions_data[it].entry;
for (; it < vec_size(code_functions); it++) {
size_t j = code_functions[it].entry;
util_debug("GEN", " {.entry =% 5d, .firstlocal =% 5d, .locals =% 5d, .profile =% 5d, .name =% 5d, .file =% 5d, .nargs =% 5d, .argsize ={%d,%d,%d,%d,%d,%d,%d,%d} }\n",
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,
code_functions_data[it].argsize[0],
code_functions_data[it].argsize[1],
code_functions_data[it].argsize[2],
code_functions_data[it].argsize[3],
code_functions_data[it].argsize[4],
code_functions_data[it].argsize[5],
code_functions_data[it].argsize[6],
code_functions_data[it].argsize[7]
code_functions[it].entry,
code_functions[it].firstlocal,
code_functions[it].locals,
code_functions[it].profile,
code_functions[it].name,
code_functions[it].file,
code_functions[it].nargs,
code_functions[it].argsize[0],
code_functions[it].argsize[1],
code_functions[it].argsize[2],
code_functions[it].argsize[3],
code_functions[it].argsize[4],
code_functions[it].argsize[5],
code_functions[it].argsize[6],
code_functions[it].argsize[7]
);
util_debug("GEN", " NAME: %s\n", &code_chars_data[code_functions_data[it].name]);
util_debug("GEN", " NAME: %s\n", &code_chars[code_functions[it].name]);
/* Internal functions have no code */
if (code_functions_data[it].entry >= 0) {
if (code_functions[it].entry >= 0) {
util_debug("GEN", " CODE:\n");
for (;;) {
if (code_statements_data[j].opcode != AINSTR_END)
if (code_statements[j].opcode != AINSTR_END)
util_debug("GEN", " %-12s {% 5i,% 5i,% 5i}\n",
asm_instr[code_statements_data[j].opcode].m,
code_statements_data[j].o1.s1,
code_statements_data[j].o2.s1,
code_statements_data[j].o3.s1
asm_instr[code_statements[j].opcode].m,
code_statements[j].o1.s1,
code_statements[j].o2.s1,
code_statements[j].o3.s1
);
else {
util_debug("GEN", " DONE {0x00000,0x00000,0x00000}\n");
@ -280,12 +246,12 @@ bool code_write(const char *filename) {
}
}
mem_d(code_statements_data);
mem_d(code_defs_data);
mem_d(code_fields_data);
mem_d(code_functions_data);
mem_d(code_globals_data);
mem_d(code_chars_data);
vec_free(code_statements);
vec_free(code_defs);
vec_free(code_fields);
vec_free(code_functions);
vec_free(code_globals);
vec_free(code_chars);
fclose(fp);
return true;
}

275
exec.c
View file

@ -29,28 +29,21 @@
#include "gmqcc.h"
MEM_VEC_FUNCTIONS(qc_program, prog_section_statement, code)
MEM_VEC_FUNCTIONS(qc_program, prog_section_def, defs)
MEM_VEC_FUNCTIONS(qc_program, prog_section_def, fields)
MEM_VEC_FUNCTIONS(qc_program, prog_section_function, functions)
MEM_VEC_FUNCTIONS(qc_program, char, strings)
MEM_VEC_FUN_APPEND(qc_program, char, strings)
MEM_VEC_FUN_RESIZE(qc_program, char, strings)
MEM_VEC_FUNCTIONS(qc_program, qcint, globals)
MEM_VEC_FUNCTIONS(qc_program, qcint, entitydata)
MEM_VEC_FUNCTIONS(qc_program, bool, entitypool)
MEM_VEC_FUNCTIONS(qc_program, qcint, localstack)
MEM_VEC_FUN_APPEND(qc_program, qcint, localstack)
MEM_VEC_FUN_RESIZE(qc_program, qcint, localstack)
MEM_VEC_FUNCTIONS(qc_program, qc_exec_stack, stack)
MEM_VEC_FUNCTIONS(qc_program, size_t, profile)
MEM_VEC_FUN_RESIZE(qc_program, size_t, profile)
MEM_VEC_FUNCTIONS(qc_program, prog_builtin, builtins)
MEM_VEC_FUNCTIONS(qc_program, const char*, function_stack)
/*
(prog_section_statement, code)
(prog_section_def, defs)
(prog_section_def, fields)
(prog_section_function, functions)
(char, strings)
(qcint, globals)
(qcint, entitydata)
(bool, entitypool)
(qcint, localstack)
(qc_exec_stack, stack)
(size_t, profile)
(prog_builtin, builtins)
(const char*, function_stack)
*/
static void loaderror(const char *fmt, ...)
{
@ -78,7 +71,6 @@ qc_program* prog_load(const char *filename)
{
qc_program *prog;
prog_header header;
size_t i;
FILE *file;
file = util_fopen(filename, "rb");
@ -114,67 +106,57 @@ qc_program* prog_load(const char *filename)
goto error;
}
#define read_data(hdrvar, progvar, type) \
#define read_data(hdrvar, progvar, reserved) \
if (fseek(file, header.hdrvar.offset, SEEK_SET) != 0) { \
loaderror("seek failed"); \
goto error; \
} \
prog->progvar##_alloc = header.hdrvar.length; \
prog->progvar##_count = header.hdrvar.length; \
prog->progvar = (type*)mem_a(header.hdrvar.length * sizeof(*prog->progvar)); \
if (!prog->progvar) \
goto error; \
if (fread(prog->progvar, sizeof(*prog->progvar), header.hdrvar.length, file) \
!= header.hdrvar.length) { \
if (fread(vec_add(prog->progvar, header.hdrvar.length + reserved), \
sizeof(*prog->progvar), \
header.hdrvar.length, file) \
!= header.hdrvar.length) \
{ \
loaderror("read failed"); \
goto error; \
}
#define read_data1(x, y) read_data(x, x, y)
#define read_data1(x) read_data(x, x, 0)
#define read_data2(x, y) read_data(x, x, y)
read_data (statements, code, prog_section_statement);
read_data1(defs, prog_section_def);
read_data1(fields, prog_section_def);
read_data1(functions, prog_section_function);
read_data1(strings, char);
read_data1(globals, qcint);
read_data (statements, code, 0);
read_data1(defs);
read_data1(fields);
read_data1(functions);
read_data1(strings);
read_data2(globals, 2); /* reserve more in case a RETURN using with the global at "the end" exists */
fclose(file);
/* profile counters */
if (!qc_program_profile_resize(prog, prog->code_count))
goto error;
memset(vec_add(prog->profile, vec_size(prog->code)), 0, sizeof(prog->profile[0]) * vec_size(prog->code));
/* Add tempstring area */
prog->tempstring_start = prog->strings_count;
prog->tempstring_at = prog->strings_count;
if (!qc_program_strings_resize(prog, prog->strings_count + 16*1024))
goto error;
prog->tempstring_start = vec_size(prog->strings);
prog->tempstring_at = vec_size(prog->strings);
memset(vec_add(prog->strings, 16*1024), 0, 16*1024);
/* spawn the world entity */
if (!qc_program_entitypool_add(prog, true)) {
loaderror("failed to allocate world entity\n");
goto error;
}
for (i = 0; i < prog->entityfields; ++i) {
if (!qc_program_entitydata_add(prog, 0)) {
loaderror("failed to allocate world data\n");
goto error;
}
}
vec_push(prog->entitypool, true);
memset(vec_add(prog->entitydata, prog->entityfields), 0, prog->entityfields * sizeof(prog->entitydata[0]));
prog->entities = 1;
return prog;
error:
if (prog->filename) mem_d(prog->filename);
if (prog->code) mem_d(prog->code);
if (prog->defs) mem_d(prog->defs);
if (prog->fields) mem_d(prog->fields);
if (prog->functions) mem_d(prog->functions);
if (prog->strings) mem_d(prog->strings);
if (prog->globals) mem_d(prog->globals);
if (prog->entitydata) mem_d(prog->entitydata);
if (prog->entitypool) mem_d(prog->entitypool);
if (prog->filename)
mem_d(prog->filename);
vec_free(prog->code);
vec_free(prog->defs);
vec_free(prog->fields);
vec_free(prog->functions);
vec_free(prog->strings);
vec_free(prog->globals);
vec_free(prog->entitydata);
vec_free(prog->entitypool);
mem_d(prog);
return NULL;
}
@ -182,22 +164,17 @@ error:
void prog_delete(qc_program *prog)
{
if (prog->filename) mem_d(prog->filename);
MEM_VECTOR_CLEAR(prog, code);
MEM_VECTOR_CLEAR(prog, defs);
MEM_VECTOR_CLEAR(prog, fields);
MEM_VECTOR_CLEAR(prog, functions);
MEM_VECTOR_CLEAR(prog, strings);
MEM_VECTOR_CLEAR(prog, globals);
MEM_VECTOR_CLEAR(prog, entitydata);
MEM_VECTOR_CLEAR(prog, entitypool);
MEM_VECTOR_CLEAR(prog, localstack);
MEM_VECTOR_CLEAR(prog, stack);
MEM_VECTOR_CLEAR(prog, profile);
if (prog->builtins_alloc) {
MEM_VECTOR_CLEAR(prog, builtins);
}
/* otherwise the builtins were statically allocated */
vec_free(prog->code);
vec_free(prog->defs);
vec_free(prog->fields);
vec_free(prog->functions);
vec_free(prog->strings);
vec_free(prog->globals);
vec_free(prog->entitydata);
vec_free(prog->entitypool);
vec_free(prog->localstack);
vec_free(prog->stack);
vec_free(prog->profile);
mem_d(prog);
}
@ -207,7 +184,7 @@ void prog_delete(qc_program *prog)
char* prog_getstring(qc_program *prog, qcint str)
{
if (str < 0 || str >= prog->strings_count)
if (str < 0 || str >= vec_size(prog->strings))
return "<<<invalid string>>>";
return prog->strings + str;
}
@ -215,7 +192,7 @@ char* prog_getstring(qc_program *prog, qcint str)
prog_section_def* prog_entfield(qc_program *prog, qcint off)
{
size_t i;
for (i = 0; i < prog->fields_count; ++i) {
for (i = 0; i < vec_size(prog->fields); ++i) {
if (prog->fields[i].offset == off)
return (prog->fields + i);
}
@ -225,7 +202,7 @@ prog_section_def* prog_entfield(qc_program *prog, qcint off)
prog_section_def* prog_getdef(qc_program *prog, qcint off)
{
size_t i;
for (i = 0; i < prog->defs_count; ++i) {
for (i = 0; i < vec_size(prog->defs); ++i) {
if (prog->defs[i].offset == off)
return (prog->defs + i);
}
@ -234,7 +211,7 @@ prog_section_def* prog_getdef(qc_program *prog, qcint off)
qcany* prog_getedict(qc_program *prog, qcint e)
{
if (e >= prog->entitypool_count) {
if (e >= vec_size(prog->entitypool)) {
prog->vmerror++;
printf("Accessing out of bounds edict %i\n", (int)e);
e = 0;
@ -245,28 +222,17 @@ qcany* prog_getedict(qc_program *prog, qcint e)
qcint prog_spawn_entity(qc_program *prog)
{
char *data;
size_t i;
qcint e;
for (e = 0; e < (qcint)prog->entitypool_count; ++e) {
for (e = 0; e < (qcint)vec_size(prog->entitypool); ++e) {
if (!prog->entitypool[e]) {
data = (char*)(prog->entitydata + (prog->entityfields * e));
memset(data, 0, prog->entityfields * sizeof(qcint));
return e;
}
}
if (!qc_program_entitypool_add(prog, true)) {
prog->vmerror++;
printf("Failed to allocate entity\n");
return 0;
}
vec_push(prog->entitypool, true);
prog->entities++;
for (i = 0; i < prog->entityfields; ++i) {
if (!qc_program_entitydata_add(prog, 0)) {
printf("Failed to allocate entity\n");
return 0;
}
}
data = (char*)(prog->entitydata + (prog->entityfields * e));
data = (char*)vec_add(prog->entitydata, prog->entityfields);
memset(data, 0, prog->entityfields * sizeof(qcint));
return e;
}
@ -278,7 +244,7 @@ void prog_free_entity(qc_program *prog, qcint e)
printf("Trying to free world entity\n");
return;
}
if (e >= prog->entitypool_count) {
if (e >= vec_size(prog->entitypool)) {
prog->vmerror++;
printf("Trying to free out of bounds entity\n");
return;
@ -302,17 +268,14 @@ qcint prog_tempstring(qc_program *prog, const char *_str)
size_t at = prog->tempstring_at;
/* when we reach the end we start over */
if (at + len >= prog->strings_count)
if (at + len >= vec_size(prog->strings))
at = prog->tempstring_start;
/* when it doesn't fit, reallocate */
if (at + len >= prog->strings_count)
if (at + len >= vec_size(prog->strings))
{
prog->strings_count = at;
if (!qc_program_strings_append(prog, str, len+1)) {
prog->vmerror = VMERR_TEMPSTRING_ALLOC;
return 0;
}
(void)vec_add(prog->strings, len+1);
memcpy(prog->strings + at, str, len+1);
return at;
}
@ -419,11 +382,11 @@ static void prog_print_statement(qc_program *prog, prog_section_statement *st)
printf("<illegal instruction %d>\n", st->opcode);
return;
}
if ((prog->xflags & VMXF_TRACE) && prog->function_stack_count) {
if ((prog->xflags & VMXF_TRACE) && vec_size(prog->function_stack)) {
size_t i;
for (i = 0; i < prog->function_stack_count; ++i)
for (i = 0; i < vec_size(prog->function_stack); ++i)
printf("->");
printf("%s:", prog->function_stack[prog->function_stack_count-1]);
printf("%s:", vec_last(prog->function_stack));
}
printf(" <> %-12s", asm_instr[st->opcode].m);
if (st->opcode >= INSTR_IF &&
@ -518,37 +481,29 @@ static qcint prog_enterfunction(qc_program *prog, prog_section_function *func)
size_t p, parampos;
/* back up locals */
st.localsp = prog->localstack_count;
st.localsp = vec_size(prog->localstack);
st.stmt = prog->statement;
st.function = func;
if (prog->xflags & VMXF_TRACE) {
(void)!qc_program_function_stack_add(prog, prog_getstring(prog, func->name));
vec_push(prog->function_stack, prog_getstring(prog, func->name));
}
#ifdef QCVM_BACKUP_STRATEGY_CALLER_VARS
if (prog->stack_count)
if (vec_size(prog->stack))
{
prog_section_function *cur;
cur = prog->stack[prog->stack_count-1].function;
cur = prog->stack[vec_size(prog->stack)-1].function;
if (cur)
{
qcint *globals = prog->globals + cur->firstlocal;
if (!qc_program_localstack_append(prog, globals, cur->locals))
{
printf("out of memory\n");
exit(1);
}
vec_append(prog->localstack, cur->locals, globals);
}
}
#else
{
qcint *globals = prog->globals + func->firstlocal;
if (!qc_program_localstack_append(prog, globals, func->locals))
{
printf("out of memory\n");
exit(1);
}
vec_append(prog->localstack, func->locals, globals);
}
#endif
@ -563,10 +518,7 @@ static qcint prog_enterfunction(qc_program *prog, prog_section_function *func)
}
}
if (!qc_program_stack_add(prog, st)) {
printf("out of memory\n");
exit(1);
}
vec_push(prog->stack, st);
return func->entry;
}
@ -576,35 +528,30 @@ static qcint prog_leavefunction(qc_program *prog)
prog_section_function *prev = NULL;
size_t oldsp;
qc_exec_stack st = prog->stack[prog->stack_count-1];
qc_exec_stack st = vec_last(prog->stack);
if (prog->xflags & VMXF_TRACE) {
if (prog->function_stack_count)
prog->function_stack_count--;
if (vec_size(prog->function_stack))
vec_pop(prog->function_stack);
}
#ifdef QCVM_BACKUP_STRATEGY_CALLER_VARS
if (prog->stack_count > 1) {
prev = prog->stack[prog->stack_count-2].function;
oldsp = prog->stack[prog->stack_count-2].localsp;
if (vec_size(prog->stack) > 1) {
prev = prog->stack[vec_size(prog->stack)-2].function;
oldsp = prog->stack[vec_size(prog->stack)-2].localsp;
}
#else
prev = prog->stack[prog->stack_count-1].function;
oldsp = prog->stack[prog->stack_count-1].localsp;
prev = prog->stack[vec_size(prog->stack)-1].function;
oldsp = prog->stack[vec_size(prog->stack)-1].localsp;
#endif
if (prev) {
qcint *globals = prog->globals + prev->firstlocal;
memcpy(globals, prog->localstack + oldsp, prev->locals);
if (!qc_program_localstack_resize(prog, oldsp)) {
printf("out of memory\n");
exit(1);
}
/* vec_remove(prog->localstack, oldsp, vec_size(prog->localstack)-oldsp); */
vec_shrinkto(prog->localstack, oldsp);
}
if (!qc_program_stack_remove(prog, prog->stack_count-1)) {
printf("out of memory\n");
exit(1);
}
vec_pop(prog->stack);
return st.stmt - 1; /* offset the ++st */
}
@ -656,8 +603,8 @@ bool prog_exec(qc_program *prog, prog_section_function *func, size_t flags, long
cleanup:
prog->xflags = oldxflags;
prog->localstack_count = 0;
prog->stack_count = 0;
vec_free(prog->localstack);
vec_free(prog->stack);
if (prog->vmerror)
return false;
return true;
@ -693,7 +640,7 @@ typedef struct {
const char *value;
} qcvm_parameter;
VECTOR_MAKE(qcvm_parameter, main_params);
qcvm_parameter *main_params = NULL;
#define CheckArgs(num) do { \
if (prog->argc != (num)) { \
@ -827,33 +774,33 @@ static void prog_main_setparams(qc_program *prog)
size_t i;
qcany *arg;
for (i = 0; i < main_params_elements; ++i) {
for (i = 0; i < vec_size(main_params); ++i) {
arg = GetGlobal(OFS_PARM0 + 3*i);
arg->vector[0] = 0;
arg->vector[1] = 0;
arg->vector[2] = 0;
switch (main_params_data[i].vtype) {
switch (main_params[i].vtype) {
case TYPE_VECTOR:
#ifdef WIN32
(void)sscanf_s(main_params_data[i].value, " %f %f %f ",
(void)sscanf_s(main_params[i].value, " %f %f %f ",
&arg->vector[0],
&arg->vector[1],
&arg->vector[2]);
#else
(void)sscanf(main_params_data[i].value, " %f %f %f ",
(void)sscanf(main_params[i].value, " %f %f %f ",
&arg->vector[0],
&arg->vector[1],
&arg->vector[2]);
#endif
break;
case TYPE_FLOAT:
arg->_float = atof(main_params_data[i].value);
arg->_float = atof(main_params[i].value);
break;
case TYPE_STRING:
arg->string = prog_tempstring(prog, main_params_data[i].value);
arg->string = prog_tempstring(prog, main_params[i].value);
break;
default:
printf("error: unhandled parameter type: %i\n", main_params_data[i].vtype);
printf("error: unhandled parameter type: %i\n", main_params[i].vtype);
break;
}
}
@ -925,12 +872,7 @@ int main(int argc, char **argv)
usage();
p.value = argv[1];
if (main_params_add(p) < 0) {
if (main_params_data)
mem_d(main_params_data);
printf("cannot add parameter\n");
exit(1);
}
vec_push(main_params, p);
--argc;
++argv;
}
@ -947,14 +889,13 @@ int main(int argc, char **argv)
prog->builtins = qc_builtins;
prog->builtins_count = qc_builtins_count;
prog->builtins_alloc = 0;
if (opts_info) {
printf("Program's system-checksum = 0x%04x\n", (int)prog->crc16);
printf("Entity field space: %i\n", (int)prog->entityfields);
}
for (i = 1; i < prog->functions_count; ++i) {
for (i = 1; i < vec_size(prog->functions); ++i) {
const char *name = prog_getstring(prog, prog->functions[i].name);
/* printf("Found function: %s\n", name); */
if (!strcmp(name, "main"))
@ -965,12 +906,12 @@ int main(int argc, char **argv)
return 0;
}
if (opts_disasm) {
for (i = 1; i < prog->functions_count; ++i)
for (i = 1; i < vec_size(prog->functions); ++i)
prog_disasm_function(prog, i);
return 0;
}
if (opts_printdefs) {
for (i = 0; i < prog->defs_count; ++i) {
for (i = 0; i < vec_size(prog->defs); ++i) {
printf("Global: %8s %-16s at %u\n",
type_name[prog->defs[i].type & DEF_TYPEMASK],
prog_getstring(prog, prog->defs[i].name),
@ -978,7 +919,7 @@ int main(int argc, char **argv)
}
}
else if (opts_printfields) {
for (i = 0; i < prog->fields_count; ++i) {
for (i = 0; i < vec_size(prog->fields); ++i) {
printf("Field: %8s %-16s at %u\n",
type_name[prog->fields[i].type],
prog_getstring(prog, prog->fields[i].name),
@ -1068,7 +1009,7 @@ while (1) {
GLOBAL(OFS_RETURN)->ivector[2] = OPA->ivector[2];
st = prog->code + prog_leavefunction(prog);
if (!prog->stack_count)
if (!vec_size(prog->stack))
goto cleanup;
break;
@ -1236,7 +1177,7 @@ while (1) {
case INSTR_STOREP_ENT:
case INSTR_STOREP_FLD:
case INSTR_STOREP_FNC:
if (OPB->_int < 0 || OPB->_int >= prog->entitydata_count) {
if (OPB->_int < 0 || OPB->_int >= vec_size(prog->entitydata)) {
qcvmerror(prog, "`%s` attempted to write to an out of bounds edict (%i)", prog->filename, OPB->_int);
goto cleanup;
}
@ -1249,7 +1190,7 @@ while (1) {
ptr->_int = OPA->_int;
break;
case INSTR_STOREP_V:
if (OPB->_int < 0 || OPB->_int + 2 >= prog->entitydata_count) {
if (OPB->_int < 0 || OPB->_int + 2 >= vec_size(prog->entitydata)) {
qcvmerror(prog, "`%s` attempted to write to an out of bounds edict (%i)", prog->filename, OPB->_int);
goto cleanup;
}
@ -1314,7 +1255,7 @@ while (1) {
if (!OPA->function)
qcvmerror(prog, "NULL function in `%s`", prog->filename);
if(!OPA->function || OPA->function >= (unsigned int)prog->functions_count)
if(!OPA->function || OPA->function >= (unsigned int)vec_size(prog->functions))
{
qcvmerror(prog, "CALL outside the program in `%s`", prog->filename);
goto cleanup;

121
gmqcc.h
View file

@ -191,8 +191,9 @@ typedef char intptr_size_is_correct [sizeof(uintptr_t)== sizeof(int*)?1:-1];
/*===================================================================*/
FILE *util_fopen(const char *filename, const char *mode);
void *util_memory_a (unsigned int, unsigned int, const char *);
void *util_memory_a (size_t, unsigned int, const char *);
void util_memory_d (void *, unsigned int, const char *);
void *util_memory_r (void *, size_t, unsigned int, const char *);
void util_meminfo ();
bool util_strupper (const char *);
@ -216,9 +217,11 @@ uint32_t util_crc32(uint32_t crc, const char *data, size_t len);
#ifdef NOTRACK
# define mem_a(x) malloc(x)
# define mem_d(x) free (x)
# define mem_r(x, n) free (x, n)
#else
# define mem_a(x) util_memory_a((x), __LINE__, __FILE__)
# define mem_d(x) util_memory_d((x), __LINE__, __FILE__)
# define mem_r(x, n) util_memory_r((x), (n), __LINE__, __FILE__)
#endif
/*
@ -229,50 +232,27 @@ uint32_t util_crc32(uint32_t crc, const char *data, size_t len);
#define FLT2INT(Y) *((int32_t*)&(Y))
#define INT2FLT(Y) *((float *)&(Y))
/* Builds vector type (usefull for inside structures) */
#define VECTOR_SNAP(X,Y) X ## Y
#define VECTOR_FILL(X,Y) VECTOR_SNAP(X,Y)
#define VECTOR_TYPE(T,N) \
T* N##_data = NULL; \
long N##_elements = 0; \
long N##_allocated = 0
/* 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; \
} \
if (!(temp = mem_a(N##_allocated * sizeof(T)))) { \
mem_d(temp); \
return -1; \
} \
memcpy(temp, N##_data, (N##_elements * sizeof(T))); \
mem_d(N##_data); \
N##_data = (T*)temp; \
} \
N##_data[N##_elements] = element; \
return N##_elements++; \
} \
int N##_put(T* elements, size_t len) { \
len --; \
elements--; \
while (N##_add(*++elements) != -1 && len--); \
return N##_elements; \
} \
typedef char VECTOR_FILL(extra_semicolon_##N,__COUNTER__)
#define VECTOR_PROT(T,N) \
extern T* N##_data ; \
extern long N##_elements ; \
extern long N##_allocated; \
int N##_add(T); \
int N##_put(T *, size_t)
#define VECTOR_MAKE(T,N) \
VECTOR_TYPE(T,N); \
VECTOR_CORE(T,N)
/* New flexible vector implementation from Dale */
#define _vec_raw(A) (((size_t*)(A)) - 2)
#define _vec_beg(A) (_vec_raw(A)[0])
#define _vec_end(A) (_vec_raw(A)[1])
#define _vec_needsgrow(A,N) ((!(A)) || (_vec_end(A) + (N) >= _vec_beg(A)))
#define _vec_mightgrow(A,N) (_vec_needsgrow((A), (N)) ? _vec_forcegrow((A),(N)) : 0)
#define _vec_forcegrow(A,N) _util_vec_grow((void**)&(A), (N), sizeof(*(A)))
void _util_vec_grow(void **a, size_t i, size_t s);
/* exposed interface */
#define vec_free(A) ((A) ? (mem_d(_vec_raw(A)), (A) = NULL) : 0)
#define vec_push(A,V) (_vec_mightgrow((A),1), (A)[_vec_end(A)++] = (V))
#define vec_size(A) ((A) ? _vec_end(A) : 0)
#define vec_add(A,N) (_vec_mightgrow((A),(N)), _vec_end(A)+=(N), &(A)[_vec_end(A)-(N)])
#define vec_last(A) ((A)[_vec_end(A)-1])
#define vec_append(A,N,S) memcpy(vec_add((A), (N)), (S), N * sizeof(*(S)))
#define _vec_remove(A,S,I,N) (memmove((char*)(A)+(I)*(S),(char*)(A)+((I)+(N))*(S),(S)*(vec_size(A)-(I)-(N))), _vec_end(A)-=(N))
#define vec_remove(A,I,N) _vec_remove((A), sizeof(*(A)), (I), (N))
#define vec_pop(A) vec_remove((A), _vec_end(A)-1, 1)
/* these are supposed to NOT reallocate */
#define vec_shrinkto(A,N) (_vec_end(A) = (N))
#define vec_shrinkby(A,N) (_vec_end(A) -= (N))
/*===================================================================*/
/*=========================== code.c ================================*/
@ -499,24 +479,12 @@ enum {
VINSTR_COND
};
/*
* The symbols below are created by the following
* expanded macros:
*
* VECTOR_MAKE(prog_section_statement, code_statements);
* VECTOR_MAKE(prog_section_def, code_defs );
* VECTOR_MAKE(prog_section_field, code_fields );
* VECTOR_MAKE(prog_section_function, code_functions );
* VECTOR_MAKE(int, code_globals );
* VECTOR_MAKE(char, code_chars );
*/
VECTOR_PROT(prog_section_statement, code_statements);
VECTOR_PROT(prog_section_statement, code_statements);
VECTOR_PROT(prog_section_def, code_defs );
VECTOR_PROT(prog_section_field, code_fields );
VECTOR_PROT(prog_section_function, code_functions );
VECTOR_PROT(int, code_globals );
VECTOR_PROT(char, code_chars );
extern prog_section_statement *code_statements;
extern prog_section_def *code_defs;
extern prog_section_field *code_fields;
extern prog_section_function *code_functions;
extern int *code_globals;
extern char *code_chars;
extern uint16_t code_crc;
typedef float qcfloat;
@ -900,16 +868,16 @@ typedef struct {
typedef struct qc_program_s {
char *filename;
MEM_VECTOR_MAKE(prog_section_statement, code);
MEM_VECTOR_MAKE(prog_section_def, defs);
MEM_VECTOR_MAKE(prog_section_def, fields);
MEM_VECTOR_MAKE(prog_section_function, functions);
MEM_VECTOR_MAKE(char, strings);
MEM_VECTOR_MAKE(qcint, globals);
MEM_VECTOR_MAKE(qcint, entitydata);
MEM_VECTOR_MAKE(bool, entitypool);
prog_section_statement *code;
prog_section_def *defs;
prog_section_def *fields;
prog_section_function *functions;
char *strings;
qcint *globals;
qcint *entitydata;
bool *entitypool;
MEM_VECTOR_MAKE(const char*, function_stack);
const char* *function_stack;
uint16_t crc16;
@ -918,17 +886,18 @@ typedef struct qc_program_s {
qcint vmerror;
MEM_VECTOR_MAKE(size_t, profile);
size_t *profile;
MEM_VECTOR_MAKE(prog_builtin, builtins);
prog_builtin *builtins;
size_t builtins_count;
/* size_t ip; */
qcint entities;
size_t entityfields;
bool allowworldwrites;
MEM_VECTOR_MAKE(qcint, localstack);
MEM_VECTOR_MAKE(qc_exec_stack, stack);
qcint *localstack;
qc_exec_stack *stack;
size_t statement;
size_t xflags;

788
ir.c

File diff suppressed because it is too large Load diff

71
ir.h
View file

@ -43,8 +43,8 @@ typedef struct ir_value_s {
/* and the output type of a function */
int outtype;
MEM_VECTOR_MAKE(struct ir_instr_s*, reads);
MEM_VECTOR_MAKE(struct ir_instr_s*, writes);
struct ir_instr_s **reads;
struct ir_instr_s **writes;
/* constantvalues */
bool isconst;
@ -72,7 +72,7 @@ typedef struct ir_value_s {
struct ir_value_s *memberof;
/* For the temp allocator */
MEM_VECTOR_MAKE(ir_life_entry_t, life);
ir_life_entry_t *life;
} ir_value;
int32_t ir_value_code_addr(const ir_value*);
@ -87,8 +87,7 @@ void ir_value_delete(ir_value*);
bool ir_value_set_name(ir_value*, const char *name);
ir_value* ir_value_vector_member(ir_value*, unsigned int member);
MEM_VECTOR_PROTO_ALL(ir_value, struct ir_instr_s*, reads);
MEM_VECTOR_PROTO_ALL(ir_value, struct ir_instr_s*, writes);
bool GMQCC_WARN vec_ir_value_find(ir_value **vec, ir_value *what, size_t *idx);
bool GMQCC_WARN ir_value_set_float(ir_value*, float f);
bool GMQCC_WARN ir_value_set_func(ir_value*, int f);
@ -101,7 +100,6 @@ bool GMQCC_WARN ir_value_set_field(ir_value*, ir_value *fld);
/*bool ir_value_set_pointer_v(ir_value*, ir_value* p); */
/*bool ir_value_set_pointer_i(ir_value*, int i); */
MEM_VECTOR_PROTO(ir_value, ir_life_entry_t, life);
/* merge an instruction into the life-range */
/* returns false if the lifepoint was already known */
bool ir_value_life_merge(ir_value*, size_t);
@ -114,12 +112,6 @@ bool ir_values_overlap(const ir_value*, const ir_value*);
void ir_value_dump(ir_value*, int (*oprintf)(const char*,...));
void ir_value_dump_life(const ir_value *self, int (*oprintf)(const char*,...));
/* A vector of IR values */
typedef struct {
MEM_VECTOR_MAKE(ir_value*, v);
} ir_value_vector;
MEM_VECTOR_PROTO(ir_value_vector, ir_value*, v);
/* PHI data */
typedef struct ir_phi_entry_s
{
@ -135,8 +127,8 @@ typedef struct ir_instr_s
ir_value* (_ops[3]);
struct ir_block_s* (bops[2]);
MEM_VECTOR_MAKE(ir_phi_entry_t, phi);
MEM_VECTOR_MAKE(ir_value*, params);
ir_phi_entry_t *phi;
ir_value **params;
/* For the temp-allocation */
size_t eid;
@ -147,10 +139,9 @@ typedef struct ir_instr_s
ir_instr* ir_instr_new(struct ir_block_s *owner, int opcode);
void ir_instr_delete(ir_instr*);
MEM_VECTOR_PROTO(ir_value, ir_phi_entry_t, phi);
bool GMQCC_WARN ir_instr_op(ir_instr*, int op, ir_value *value, bool writing);
bool GMQCC_WARN vec_ir_instr_find(ir_instr **vec, ir_instr *what, size_t *idx);
MEM_VECTOR_PROTO(ir_value, ir_value*, params);
bool GMQCC_WARN ir_instr_op(ir_instr*, int op, ir_value *value, bool writing);
void ir_instr_dump(ir_instr* in, char *ind, int (*oprintf)(const char*,...));
@ -161,10 +152,10 @@ typedef struct ir_block_s
lex_ctx context;
bool final; /* once a jump is added we're done */
MEM_VECTOR_MAKE(ir_instr*, instr);
MEM_VECTOR_MAKE(struct ir_block_s*, entries);
MEM_VECTOR_MAKE(struct ir_block_s*, exits);
MEM_VECTOR_MAKE(ir_value*, living);
ir_instr **instr;
struct ir_block_s **entries;
struct ir_block_s **exits;
ir_value **living;
/* For the temp-allocation */
size_t eid;
@ -182,10 +173,6 @@ void ir_block_delete(ir_block*);
bool ir_block_set_label(ir_block*, const char *label);
MEM_VECTOR_PROTO(ir_block, ir_instr*, instr);
MEM_VECTOR_PROTO_ALL(ir_block, ir_block*, exits);
MEM_VECTOR_PROTO_ALL(ir_block, ir_block*, entries);
ir_value* ir_block_create_binop(ir_block*, const char *label, int op,
ir_value *left, ir_value *right);
ir_value* ir_block_create_unary(ir_block*, const char *label, int op,
@ -211,10 +198,10 @@ ir_value* ir_block_create_mul(ir_block*, const char *label, ir_value *l, ir_valu
ir_value* ir_block_create_div(ir_block*, const char *label, ir_value *l, ir_value *r);
ir_instr* ir_block_create_phi(ir_block*, const char *label, int vtype);
ir_value* ir_phi_value(ir_instr*);
bool GMQCC_WARN ir_phi_add(ir_instr*, ir_block *b, ir_value *v);
void ir_phi_add(ir_instr*, ir_block *b, ir_value *v);
ir_instr* ir_block_create_call(ir_block*, const char *label, ir_value *func);
ir_value* ir_call_value(ir_instr*);
bool GMQCC_WARN ir_call_param(ir_instr*, ir_value*);
void ir_call_param(ir_instr*, ir_value*);
bool GMQCC_WARN ir_block_create_return(ir_block*, ir_value *opt_value);
@ -229,8 +216,6 @@ bool GMQCC_WARN ir_block_create_if(ir_block*, ir_value *cond,
bool GMQCC_WARN ir_block_create_jump(ir_block*, ir_block *to);
bool GMQCC_WARN ir_block_create_goto(ir_block*, ir_block *to);
MEM_VECTOR_PROTO_ALL(ir_block, ir_value*, living);
void ir_block_dump(ir_block*, char *ind, int (*oprintf)(const char*,...));
/* function */
@ -239,8 +224,8 @@ typedef struct ir_function_s
{
char *name;
int outtype;
MEM_VECTOR_MAKE(int, params);
MEM_VECTOR_MAKE(ir_block*, blocks);
int *params;
ir_block **blocks;
int builtin;
@ -250,10 +235,10 @@ typedef struct ir_function_s
* which might get optimized away, so anything
* in there needs to be deleted in the dtor.
*/
MEM_VECTOR_MAKE(ir_value*, values);
ir_value **values;
/* locally defined variables */
MEM_VECTOR_MAKE(ir_value*, locals);
ir_value **locals;
size_t allocated_locals;
@ -279,11 +264,9 @@ typedef struct ir_function_s
ir_function* ir_function_new(struct ir_builder_s *owner, int returntype);
void ir_function_delete(ir_function*);
bool GMQCC_WARN ir_function_collect_value(ir_function*, ir_value *value);
void ir_function_collect_value(ir_function*, ir_value *value);
bool ir_function_set_name(ir_function*, const char *name);
MEM_VECTOR_PROTO(ir_function, int, params);
MEM_VECTOR_PROTO(ir_function, ir_block*, blocks);
ir_value* ir_function_get_local(ir_function *self, const char *name);
ir_value* ir_function_create_local(ir_function *self, const char *name, int vtype, bool param);
@ -303,12 +286,12 @@ void ir_function_dump(ir_function*, char *ind, int (*oprintf)(const char*,...));
typedef struct ir_builder_s
{
char *name;
MEM_VECTOR_MAKE(ir_function*, functions);
MEM_VECTOR_MAKE(ir_value*, globals);
MEM_VECTOR_MAKE(ir_value*, fields);
ir_function **functions;
ir_value **globals;
ir_value **fields;
MEM_VECTOR_MAKE(const char*, filenames);
MEM_VECTOR_MAKE(qcint, filestrings);
const char **filenames;
qcint *filestrings;
/* we cache the #IMMEDIATE string here */
qcint str_immediate;
} ir_builder;
@ -318,12 +301,6 @@ void ir_builder_delete(ir_builder*);
bool ir_builder_set_name(ir_builder *self, const char *name);
MEM_VECTOR_PROTO(ir_builder, ir_function*, functions);
MEM_VECTOR_PROTO(ir_builder, ir_value*, globals);
MEM_VECTOR_PROTO(ir_builder, ir_value*, fields);
MEM_VECTOR_PROTO(ir_builder, const char*, filenames);
MEM_VECTOR_PROTO(ir_builder, qcint, filestrings);
ir_function* ir_builder_get_function(ir_builder*, const char *fun);
ir_function* ir_builder_create_function(ir_builder*, const char *name, int outtype);

13
lexer.c
View file

@ -9,7 +9,7 @@
MEM_VEC_FUNCTIONS(token, char, value)
MEM_VEC_FUNCTIONS(lex_file, frame_macro, frames)
VECTOR_MAKE(char*, lex_filenames);
char* *lex_filenames;
void lexerror(lex_file *lex, const char *fmt, ...)
{
@ -157,8 +157,7 @@ lex_file* lex_open(const char *file)
lex->peekpos = 0;
lex->eof = false;
lex_filenames_add(lex->name);
vec_push(lex_filenames, lex->name);
return lex;
}
@ -185,7 +184,7 @@ lex_file* lex_open_string(const char *str, size_t len, const char *name)
lex->peekpos = 0;
lex->eof = false;
lex_filenames_add(lex->name);
vec_push(lex_filenames, lex->name);
return lex;
}
@ -193,9 +192,9 @@ lex_file* lex_open_string(const char *str, size_t len, const char *name)
void lex_cleanup(void)
{
size_t i;
for (i = 0; i < lex_filenames_elements; ++i)
mem_d(lex_filenames_data[i]);
mem_d(lex_filenames_data);
for (i = 0; i < vec_size(lex_filenames); ++i)
mem_d(lex_filenames[i]);
vec_free(lex_filenames);
}
void lex_close(lex_file *lex)

24
main.c
View file

@ -46,7 +46,7 @@ const oper_info *operators = NULL;
size_t operator_count = 0;
typedef struct { char *filename; int type; } argitem;
VECTOR_MAKE(argitem, items);
static argitem *items = NULL;
#define TYPE_QC 0
#define TYPE_ASM 1
@ -341,7 +341,7 @@ static bool options_parse(int argc, char **argv) {
return false;
}
item.filename = argarg;
items_add(item);
vec_push(items, item);
break;
case '-':
@ -378,7 +378,7 @@ static bool options_parse(int argc, char **argv) {
argitem item;
item.filename = argv[0];
item.type = TYPE_QC;
items_add(item);
vec_push(items, item);
}
}
con_change(redirout, redirerr);
@ -471,18 +471,18 @@ int main(int argc, char **argv) {
util_debug("COM", "starting ...\n");
if (items_elements) {
if (vec_size(items)) {
con_out("Mode: manual\n");
con_out("There are %lu items to compile:\n", (unsigned long)items_elements);
for (itr = 0; itr < items_elements; ++itr) {
con_out("There are %lu items to compile:\n", (unsigned long)vec_size(items));
for (itr = 0; itr < vec_size(items); ++itr) {
con_out(" item: %s (%s)\n",
items_data[itr].filename,
( (items_data[itr].type == TYPE_QC ? "qc" :
(items_data[itr].type == TYPE_ASM ? "asm" :
(items_data[itr].type == TYPE_SRC ? "progs.src" :
items[itr].filename,
( (items[itr].type == TYPE_QC ? "qc" :
(items[itr].type == TYPE_ASM ? "asm" :
(items[itr].type == TYPE_SRC ? "progs.src" :
("unknown"))))));
if (!parser_compile_file(items_data[itr].filename))
if (!parser_compile_file(items[itr].filename))
{
retval = 1;
goto cleanup;
@ -541,7 +541,7 @@ srcdone:
cleanup:
util_debug("COM", "cleaning ...\n");
con_close();
mem_d(items_data);
vec_free(items);
parser_cleanup();
if (opts_output_free)

518
parser.c

File diff suppressed because it is too large Load diff

18
util.c
View file

@ -32,14 +32,14 @@ uint64_t mem_dt = 0;
struct memblock_t {
const char *file;
unsigned int line;
unsigned int byte;
size_t byte;
struct memblock_t *next;
struct memblock_t *prev;
};
static struct memblock_t *mem_start = NULL;
void *util_memory_a(unsigned int byte, unsigned int line, const char *file) {
void *util_memory_a(size_t byte, unsigned int line, const char *file) {
struct memblock_t *info = malloc(sizeof(struct memblock_t) + byte);
void *data = (void*)(info+1);
if (!info) return NULL;
@ -79,7 +79,7 @@ void util_memory_d(void *ptrn, unsigned int line, const char *file) {
free(info);
}
void *util_memory_r(void *ptrn, unsigned int byte, unsigned int line, const char *file) {
void *util_memory_r(void *ptrn, size_t byte, unsigned int line, const char *file) {
struct memblock_t *oldinfo = NULL;
struct memblock_t *newinfo;
@ -106,6 +106,10 @@ void *util_memory_r(void *ptrn, unsigned int byte, unsigned int line, const char
newinfo->file = file;
newinfo->next = oldinfo->next;
newinfo->prev = oldinfo->prev;
if (newinfo->next)
newinfo->next->prev = newinfo;
if (newinfo->prev)
newinfo->prev->next = newinfo;
if (mem_start == oldinfo)
mem_start = newinfo;
@ -511,3 +515,11 @@ FILE *util_fopen(const char *filename, const char *mode)
#endif
}
void _util_vec_grow(void **a, size_t i, size_t s) {
size_t m = *a ? 2*_vec_beg(*a)+i : i+1;
void *p = mem_r((*a ? _vec_raw(*a) : NULL), s * m + sizeof(size_t)*2);
if (!*a)
((size_t*)p)[1] = 0;
*a = (void*)((size_t*)p + 2);
_vec_beg(*a) = m;
}