mirror of
https://github.com/DarkPlacesEngine/gmqcc.git
synced 2024-11-23 12:22:26 +00:00
Replaced it all...
This commit is contained in:
parent
b8fc2b7731
commit
906f319673
11 changed files with 933 additions and 1320 deletions
150
ast.c
150
ast.c
|
@ -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,9 +706,8 @@ 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->func = funcexpr;
|
||||
self->params = NULL;
|
||||
self->func = funcexpr;
|
||||
|
||||
self->expression.vtype = funcexpr->expression.next->expression.vtype;
|
||||
if (funcexpr->expression.next->expression.next)
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -850,9 +844,9 @@ ast_function* ast_function_new(lex_ctx ctx, const char *name, ast_value *vtype)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
self->vtype = vtype;
|
||||
self->name = name ? util_strdup(name) : NULL;
|
||||
MEM_VECTOR_INIT(self, blocks);
|
||||
self->vtype = vtype;
|
||||
self->name = name ? util_strdup(name) : NULL;
|
||||
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(¶ms, 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(¶ms, 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(¶ms, v);
|
||||
vec_free(params);
|
||||
return true;
|
||||
error:
|
||||
MEM_VECTOR_CLEAR(¶ms, v);
|
||||
vec_free(params);
|
||||
return false;
|
||||
}
|
||||
|
|
25
ast.h
25
ast.h
|
@ -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
224
code.c
|
@ -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;
|
||||
}
|
||||
|
|
287
exec.c
287
exec.c
|
@ -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) \
|
||||
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) { \
|
||||
loaderror("read failed"); \
|
||||
goto error; \
|
||||
#define read_data(hdrvar, progvar, reserved) \
|
||||
if (fseek(file, header.hdrvar.offset, SEEK_SET) != 0) { \
|
||||
loaderror("seek failed"); \
|
||||
goto error; \
|
||||
} \
|
||||
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;
|
||||
|
|
129
gmqcc.h
129
gmqcc.h
|
@ -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 *);
|
||||
|
@ -214,11 +215,13 @@ uint16_t util_crc16(uint16_t crc, const char *data, size_t len);
|
|||
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_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_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;
|
||||
|
|
75
ir.h
75
ir.h
|
@ -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,18 +216,16 @@ 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 */
|
||||
|
||||
typedef struct ir_function_s
|
||||
{
|
||||
char *name;
|
||||
int outtype;
|
||||
MEM_VECTOR_MAKE(int, params);
|
||||
MEM_VECTOR_MAKE(ir_block*, blocks);
|
||||
char *name;
|
||||
int outtype;
|
||||
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
13
lexer.c
|
@ -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
24
main.c
|
@ -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)
|
||||
|
|
18
util.c
18
util.c
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue