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

25
ast.h
View file

@ -120,7 +120,7 @@ typedef struct
ast_expression *next; ast_expression *next;
/* arrays get a member-count */ /* arrays get a member-count */
size_t count; size_t count;
MEM_VECTOR_MAKE(ast_value*, params); ast_value* *params;
bool variadic; bool variadic;
/* The codegen functions should store their output values /* The codegen functions should store their output values
* so we can call it multiple times without re-evaluating. * so we can call it multiple times without re-evaluating.
@ -130,7 +130,6 @@ typedef struct
ir_value *outl; ir_value *outl;
ir_value *outr; ir_value *outr;
} ast_expression_common; } ast_expression_common;
MEM_VECTOR_PROTO(ast_expression_common, ast_value*, params);
/* Value /* 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_local_codegen(ast_value *self, ir_function *func, bool isparam);
bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield); 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); bool ast_compare_type(ast_expression *a, ast_expression *b);
ast_expression* ast_type_copy(lex_ctx ctx, const ast_expression *ex); 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_common expression;
ast_expression *func; ast_expression *func;
MEM_VECTOR_MAKE(ast_expression*, params); ast_expression* *params;
}; };
ast_call* ast_call_new(lex_ctx ctx, ast_call* ast_call_new(lex_ctx ctx,
ast_expression *funcexpr); 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_codegen(ast_call*, ast_function*, bool lvalue, ir_value**);
bool ast_call_check_types(ast_call*); bool ast_call_check_types(ast_call*);
MEM_VECTOR_PROTO(ast_call, ast_expression*, params);
/* Blocks /* Blocks
* *
*/ */
@ -477,20 +474,16 @@ struct ast_block_s
{ {
ast_expression_common expression; ast_expression_common expression;
MEM_VECTOR_MAKE(ast_value*, locals); ast_value* *locals;
MEM_VECTOR_MAKE(ast_expression*, exprs); ast_expression* *exprs;
MEM_VECTOR_MAKE(ast_expression*, collect); ast_expression* *collect;
}; };
ast_block* ast_block_new(lex_ctx ctx); ast_block* ast_block_new(lex_ctx ctx);
void ast_block_delete(ast_block*); void ast_block_delete(ast_block*);
bool ast_block_set_type(ast_block*, ast_expression *from); 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_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 /* Function
* *
@ -523,7 +516,7 @@ struct ast_function_s
*/ */
char labelbuf[64]; 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); ast_function* ast_function_new(lex_ctx ctx, const char *name, ast_value *vtype);
/* This will NOT delete the underlying ast_value */ /* 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); 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); bool ast_function_codegen(ast_function *self, ir_builder *builder);
/* Expression union /* Expression union

224
code.c
View file

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

275
exec.c
View file

@ -29,28 +29,21 @@
#include "gmqcc.h" #include "gmqcc.h"
MEM_VEC_FUNCTIONS(qc_program, prog_section_statement, code) /*
MEM_VEC_FUNCTIONS(qc_program, prog_section_def, defs) (prog_section_statement, code)
MEM_VEC_FUNCTIONS(qc_program, prog_section_def, fields) (prog_section_def, defs)
MEM_VEC_FUNCTIONS(qc_program, prog_section_function, functions) (prog_section_def, fields)
MEM_VEC_FUNCTIONS(qc_program, char, strings) (prog_section_function, functions)
MEM_VEC_FUN_APPEND(qc_program, char, strings) (char, strings)
MEM_VEC_FUN_RESIZE(qc_program, char, strings) (qcint, globals)
MEM_VEC_FUNCTIONS(qc_program, qcint, globals) (qcint, entitydata)
MEM_VEC_FUNCTIONS(qc_program, qcint, entitydata) (bool, entitypool)
MEM_VEC_FUNCTIONS(qc_program, bool, entitypool) (qcint, localstack)
(qc_exec_stack, stack)
MEM_VEC_FUNCTIONS(qc_program, qcint, localstack) (size_t, profile)
MEM_VEC_FUN_APPEND(qc_program, qcint, localstack) (prog_builtin, builtins)
MEM_VEC_FUN_RESIZE(qc_program, qcint, localstack) (const char*, function_stack)
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)
static void loaderror(const char *fmt, ...) static void loaderror(const char *fmt, ...)
{ {
@ -78,7 +71,6 @@ qc_program* prog_load(const char *filename)
{ {
qc_program *prog; qc_program *prog;
prog_header header; prog_header header;
size_t i;
FILE *file; FILE *file;
file = util_fopen(filename, "rb"); file = util_fopen(filename, "rb");
@ -114,67 +106,57 @@ qc_program* prog_load(const char *filename)
goto error; goto error;
} }
#define read_data(hdrvar, progvar, type) \ #define read_data(hdrvar, progvar, reserved) \
if (fseek(file, header.hdrvar.offset, SEEK_SET) != 0) { \ if (fseek(file, header.hdrvar.offset, SEEK_SET) != 0) { \
loaderror("seek failed"); \ loaderror("seek failed"); \
goto error; \ goto error; \
} \ } \
prog->progvar##_alloc = header.hdrvar.length; \ if (fread(vec_add(prog->progvar, header.hdrvar.length + reserved), \
prog->progvar##_count = header.hdrvar.length; \ sizeof(*prog->progvar), \
prog->progvar = (type*)mem_a(header.hdrvar.length * sizeof(*prog->progvar)); \ header.hdrvar.length, file) \
if (!prog->progvar) \ != header.hdrvar.length) \
goto error; \ { \
if (fread(prog->progvar, sizeof(*prog->progvar), header.hdrvar.length, file) \
!= header.hdrvar.length) { \
loaderror("read failed"); \ loaderror("read failed"); \
goto error; \ 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_data (statements, code, 0);
read_data1(defs, prog_section_def); read_data1(defs);
read_data1(fields, prog_section_def); read_data1(fields);
read_data1(functions, prog_section_function); read_data1(functions);
read_data1(strings, char); read_data1(strings);
read_data1(globals, qcint); read_data2(globals, 2); /* reserve more in case a RETURN using with the global at "the end" exists */
fclose(file); fclose(file);
/* profile counters */ /* profile counters */
if (!qc_program_profile_resize(prog, prog->code_count)) memset(vec_add(prog->profile, vec_size(prog->code)), 0, sizeof(prog->profile[0]) * vec_size(prog->code));
goto error;
/* Add tempstring area */ /* Add tempstring area */
prog->tempstring_start = prog->strings_count; prog->tempstring_start = vec_size(prog->strings);
prog->tempstring_at = prog->strings_count; prog->tempstring_at = vec_size(prog->strings);
if (!qc_program_strings_resize(prog, prog->strings_count + 16*1024)) memset(vec_add(prog->strings, 16*1024), 0, 16*1024);
goto error;
/* spawn the world entity */ /* spawn the world entity */
if (!qc_program_entitypool_add(prog, true)) { vec_push(prog->entitypool, true);
loaderror("failed to allocate world entity\n"); memset(vec_add(prog->entitydata, prog->entityfields), 0, prog->entityfields * sizeof(prog->entitydata[0]));
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;
}
}
prog->entities = 1; prog->entities = 1;
return prog; return prog;
error: error:
if (prog->filename) mem_d(prog->filename); if (prog->filename)
if (prog->code) mem_d(prog->code); mem_d(prog->filename);
if (prog->defs) mem_d(prog->defs); vec_free(prog->code);
if (prog->fields) mem_d(prog->fields); vec_free(prog->defs);
if (prog->functions) mem_d(prog->functions); vec_free(prog->fields);
if (prog->strings) mem_d(prog->strings); vec_free(prog->functions);
if (prog->globals) mem_d(prog->globals); vec_free(prog->strings);
if (prog->entitydata) mem_d(prog->entitydata); vec_free(prog->globals);
if (prog->entitypool) mem_d(prog->entitypool); vec_free(prog->entitydata);
vec_free(prog->entitypool);
mem_d(prog); mem_d(prog);
return NULL; return NULL;
} }
@ -182,22 +164,17 @@ error:
void prog_delete(qc_program *prog) void prog_delete(qc_program *prog)
{ {
if (prog->filename) mem_d(prog->filename); if (prog->filename) mem_d(prog->filename);
MEM_VECTOR_CLEAR(prog, code); vec_free(prog->code);
MEM_VECTOR_CLEAR(prog, defs); vec_free(prog->defs);
MEM_VECTOR_CLEAR(prog, fields); vec_free(prog->fields);
MEM_VECTOR_CLEAR(prog, functions); vec_free(prog->functions);
MEM_VECTOR_CLEAR(prog, strings); vec_free(prog->strings);
MEM_VECTOR_CLEAR(prog, globals); vec_free(prog->globals);
MEM_VECTOR_CLEAR(prog, entitydata); vec_free(prog->entitydata);
MEM_VECTOR_CLEAR(prog, entitypool); vec_free(prog->entitypool);
MEM_VECTOR_CLEAR(prog, localstack); vec_free(prog->localstack);
MEM_VECTOR_CLEAR(prog, stack); vec_free(prog->stack);
MEM_VECTOR_CLEAR(prog, profile); vec_free(prog->profile);
if (prog->builtins_alloc) {
MEM_VECTOR_CLEAR(prog, builtins);
}
/* otherwise the builtins were statically allocated */
mem_d(prog); mem_d(prog);
} }
@ -207,7 +184,7 @@ void prog_delete(qc_program *prog)
char* prog_getstring(qc_program *prog, qcint str) 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 "<<<invalid string>>>";
return prog->strings + str; 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) prog_section_def* prog_entfield(qc_program *prog, qcint off)
{ {
size_t i; 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) if (prog->fields[i].offset == off)
return (prog->fields + i); 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) prog_section_def* prog_getdef(qc_program *prog, qcint off)
{ {
size_t i; 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) if (prog->defs[i].offset == off)
return (prog->defs + i); 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) qcany* prog_getedict(qc_program *prog, qcint e)
{ {
if (e >= prog->entitypool_count) { if (e >= vec_size(prog->entitypool)) {
prog->vmerror++; prog->vmerror++;
printf("Accessing out of bounds edict %i\n", (int)e); printf("Accessing out of bounds edict %i\n", (int)e);
e = 0; e = 0;
@ -245,28 +222,17 @@ qcany* prog_getedict(qc_program *prog, qcint e)
qcint prog_spawn_entity(qc_program *prog) qcint prog_spawn_entity(qc_program *prog)
{ {
char *data; char *data;
size_t i;
qcint e; 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]) { if (!prog->entitypool[e]) {
data = (char*)(prog->entitydata + (prog->entityfields * e)); data = (char*)(prog->entitydata + (prog->entityfields * e));
memset(data, 0, prog->entityfields * sizeof(qcint)); memset(data, 0, prog->entityfields * sizeof(qcint));
return e; return e;
} }
} }
if (!qc_program_entitypool_add(prog, true)) { vec_push(prog->entitypool, true);
prog->vmerror++;
printf("Failed to allocate entity\n");
return 0;
}
prog->entities++; prog->entities++;
for (i = 0; i < prog->entityfields; ++i) { data = (char*)vec_add(prog->entitydata, prog->entityfields);
if (!qc_program_entitydata_add(prog, 0)) {
printf("Failed to allocate entity\n");
return 0;
}
}
data = (char*)(prog->entitydata + (prog->entityfields * e));
memset(data, 0, prog->entityfields * sizeof(qcint)); memset(data, 0, prog->entityfields * sizeof(qcint));
return e; return e;
} }
@ -278,7 +244,7 @@ void prog_free_entity(qc_program *prog, qcint e)
printf("Trying to free world entity\n"); printf("Trying to free world entity\n");
return; return;
} }
if (e >= prog->entitypool_count) { if (e >= vec_size(prog->entitypool)) {
prog->vmerror++; prog->vmerror++;
printf("Trying to free out of bounds entity\n"); printf("Trying to free out of bounds entity\n");
return; return;
@ -302,17 +268,14 @@ qcint prog_tempstring(qc_program *prog, const char *_str)
size_t at = prog->tempstring_at; size_t at = prog->tempstring_at;
/* when we reach the end we start over */ /* 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; at = prog->tempstring_start;
/* when it doesn't fit, reallocate */ /* when it doesn't fit, reallocate */
if (at + len >= prog->strings_count) if (at + len >= vec_size(prog->strings))
{ {
prog->strings_count = at; (void)vec_add(prog->strings, len+1);
if (!qc_program_strings_append(prog, str, len+1)) { memcpy(prog->strings + at, str, len+1);
prog->vmerror = VMERR_TEMPSTRING_ALLOC;
return 0;
}
return at; 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); printf("<illegal instruction %d>\n", st->opcode);
return; return;
} }
if ((prog->xflags & VMXF_TRACE) && prog->function_stack_count) { if ((prog->xflags & VMXF_TRACE) && vec_size(prog->function_stack)) {
size_t i; size_t i;
for (i = 0; i < prog->function_stack_count; ++i) for (i = 0; i < vec_size(prog->function_stack); ++i)
printf("->"); 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); printf(" <> %-12s", asm_instr[st->opcode].m);
if (st->opcode >= INSTR_IF && if (st->opcode >= INSTR_IF &&
@ -518,37 +481,29 @@ static qcint prog_enterfunction(qc_program *prog, prog_section_function *func)
size_t p, parampos; size_t p, parampos;
/* back up locals */ /* back up locals */
st.localsp = prog->localstack_count; st.localsp = vec_size(prog->localstack);
st.stmt = prog->statement; st.stmt = prog->statement;
st.function = func; st.function = func;
if (prog->xflags & VMXF_TRACE) { 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 #ifdef QCVM_BACKUP_STRATEGY_CALLER_VARS
if (prog->stack_count) if (vec_size(prog->stack))
{ {
prog_section_function *cur; prog_section_function *cur;
cur = prog->stack[prog->stack_count-1].function; cur = prog->stack[vec_size(prog->stack)-1].function;
if (cur) if (cur)
{ {
qcint *globals = prog->globals + cur->firstlocal; qcint *globals = prog->globals + cur->firstlocal;
if (!qc_program_localstack_append(prog, globals, cur->locals)) vec_append(prog->localstack, cur->locals, globals);
{
printf("out of memory\n");
exit(1);
}
} }
} }
#else #else
{ {
qcint *globals = prog->globals + func->firstlocal; qcint *globals = prog->globals + func->firstlocal;
if (!qc_program_localstack_append(prog, globals, func->locals)) vec_append(prog->localstack, func->locals, globals);
{
printf("out of memory\n");
exit(1);
}
} }
#endif #endif
@ -563,10 +518,7 @@ static qcint prog_enterfunction(qc_program *prog, prog_section_function *func)
} }
} }
if (!qc_program_stack_add(prog, st)) { vec_push(prog->stack, st);
printf("out of memory\n");
exit(1);
}
return func->entry; return func->entry;
} }
@ -576,35 +528,30 @@ static qcint prog_leavefunction(qc_program *prog)
prog_section_function *prev = NULL; prog_section_function *prev = NULL;
size_t oldsp; 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->xflags & VMXF_TRACE) {
if (prog->function_stack_count) if (vec_size(prog->function_stack))
prog->function_stack_count--; vec_pop(prog->function_stack);
} }
#ifdef QCVM_BACKUP_STRATEGY_CALLER_VARS #ifdef QCVM_BACKUP_STRATEGY_CALLER_VARS
if (prog->stack_count > 1) { if (vec_size(prog->stack) > 1) {
prev = prog->stack[prog->stack_count-2].function; prev = prog->stack[vec_size(prog->stack)-2].function;
oldsp = prog->stack[prog->stack_count-2].localsp; oldsp = prog->stack[vec_size(prog->stack)-2].localsp;
} }
#else #else
prev = prog->stack[prog->stack_count-1].function; prev = prog->stack[vec_size(prog->stack)-1].function;
oldsp = prog->stack[prog->stack_count-1].localsp; oldsp = prog->stack[vec_size(prog->stack)-1].localsp;
#endif #endif
if (prev) { if (prev) {
qcint *globals = prog->globals + prev->firstlocal; qcint *globals = prog->globals + prev->firstlocal;
memcpy(globals, prog->localstack + oldsp, prev->locals); memcpy(globals, prog->localstack + oldsp, prev->locals);
if (!qc_program_localstack_resize(prog, oldsp)) { /* vec_remove(prog->localstack, oldsp, vec_size(prog->localstack)-oldsp); */
printf("out of memory\n"); vec_shrinkto(prog->localstack, oldsp);
exit(1);
}
} }
if (!qc_program_stack_remove(prog, prog->stack_count-1)) { vec_pop(prog->stack);
printf("out of memory\n");
exit(1);
}
return st.stmt - 1; /* offset the ++st */ 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: cleanup:
prog->xflags = oldxflags; prog->xflags = oldxflags;
prog->localstack_count = 0; vec_free(prog->localstack);
prog->stack_count = 0; vec_free(prog->stack);
if (prog->vmerror) if (prog->vmerror)
return false; return false;
return true; return true;
@ -693,7 +640,7 @@ typedef struct {
const char *value; const char *value;
} qcvm_parameter; } qcvm_parameter;
VECTOR_MAKE(qcvm_parameter, main_params); qcvm_parameter *main_params = NULL;
#define CheckArgs(num) do { \ #define CheckArgs(num) do { \
if (prog->argc != (num)) { \ if (prog->argc != (num)) { \
@ -827,33 +774,33 @@ static void prog_main_setparams(qc_program *prog)
size_t i; size_t i;
qcany *arg; 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 = GetGlobal(OFS_PARM0 + 3*i);
arg->vector[0] = 0; arg->vector[0] = 0;
arg->vector[1] = 0; arg->vector[1] = 0;
arg->vector[2] = 0; arg->vector[2] = 0;
switch (main_params_data[i].vtype) { switch (main_params[i].vtype) {
case TYPE_VECTOR: case TYPE_VECTOR:
#ifdef WIN32 #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[0],
&arg->vector[1], &arg->vector[1],
&arg->vector[2]); &arg->vector[2]);
#else #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[0],
&arg->vector[1], &arg->vector[1],
&arg->vector[2]); &arg->vector[2]);
#endif #endif
break; break;
case TYPE_FLOAT: case TYPE_FLOAT:
arg->_float = atof(main_params_data[i].value); arg->_float = atof(main_params[i].value);
break; break;
case TYPE_STRING: case TYPE_STRING:
arg->string = prog_tempstring(prog, main_params_data[i].value); arg->string = prog_tempstring(prog, main_params[i].value);
break; break;
default: 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; break;
} }
} }
@ -925,12 +872,7 @@ int main(int argc, char **argv)
usage(); usage();
p.value = argv[1]; p.value = argv[1];
if (main_params_add(p) < 0) { vec_push(main_params, p);
if (main_params_data)
mem_d(main_params_data);
printf("cannot add parameter\n");
exit(1);
}
--argc; --argc;
++argv; ++argv;
} }
@ -947,14 +889,13 @@ int main(int argc, char **argv)
prog->builtins = qc_builtins; prog->builtins = qc_builtins;
prog->builtins_count = qc_builtins_count; prog->builtins_count = qc_builtins_count;
prog->builtins_alloc = 0;
if (opts_info) { if (opts_info) {
printf("Program's system-checksum = 0x%04x\n", (int)prog->crc16); printf("Program's system-checksum = 0x%04x\n", (int)prog->crc16);
printf("Entity field space: %i\n", (int)prog->entityfields); 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); const char *name = prog_getstring(prog, prog->functions[i].name);
/* printf("Found function: %s\n", name); */ /* printf("Found function: %s\n", name); */
if (!strcmp(name, "main")) if (!strcmp(name, "main"))
@ -965,12 +906,12 @@ int main(int argc, char **argv)
return 0; return 0;
} }
if (opts_disasm) { 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); prog_disasm_function(prog, i);
return 0; return 0;
} }
if (opts_printdefs) { 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", printf("Global: %8s %-16s at %u\n",
type_name[prog->defs[i].type & DEF_TYPEMASK], type_name[prog->defs[i].type & DEF_TYPEMASK],
prog_getstring(prog, prog->defs[i].name), prog_getstring(prog, prog->defs[i].name),
@ -978,7 +919,7 @@ int main(int argc, char **argv)
} }
} }
else if (opts_printfields) { 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", printf("Field: %8s %-16s at %u\n",
type_name[prog->fields[i].type], type_name[prog->fields[i].type],
prog_getstring(prog, prog->fields[i].name), prog_getstring(prog, prog->fields[i].name),
@ -1068,7 +1009,7 @@ while (1) {
GLOBAL(OFS_RETURN)->ivector[2] = OPA->ivector[2]; GLOBAL(OFS_RETURN)->ivector[2] = OPA->ivector[2];
st = prog->code + prog_leavefunction(prog); st = prog->code + prog_leavefunction(prog);
if (!prog->stack_count) if (!vec_size(prog->stack))
goto cleanup; goto cleanup;
break; break;
@ -1236,7 +1177,7 @@ while (1) {
case INSTR_STOREP_ENT: case INSTR_STOREP_ENT:
case INSTR_STOREP_FLD: case INSTR_STOREP_FLD:
case INSTR_STOREP_FNC: 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); qcvmerror(prog, "`%s` attempted to write to an out of bounds edict (%i)", prog->filename, OPB->_int);
goto cleanup; goto cleanup;
} }
@ -1249,7 +1190,7 @@ while (1) {
ptr->_int = OPA->_int; ptr->_int = OPA->_int;
break; break;
case INSTR_STOREP_V: 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); qcvmerror(prog, "`%s` attempted to write to an out of bounds edict (%i)", prog->filename, OPB->_int);
goto cleanup; goto cleanup;
} }
@ -1314,7 +1255,7 @@ while (1) {
if (!OPA->function) if (!OPA->function)
qcvmerror(prog, "NULL function in `%s`", prog->filename); 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); qcvmerror(prog, "CALL outside the program in `%s`", prog->filename);
goto cleanup; 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); 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_d (void *, unsigned int, const char *);
void *util_memory_r (void *, size_t, unsigned int, const char *);
void util_meminfo (); void util_meminfo ();
bool util_strupper (const char *); bool util_strupper (const char *);
@ -216,9 +217,11 @@ uint32_t util_crc32(uint32_t crc, const char *data, size_t len);
#ifdef NOTRACK #ifdef NOTRACK
# define mem_a(x) malloc(x) # define mem_a(x) malloc(x)
# define mem_d(x) free (x) # define mem_d(x) free (x)
# define mem_r(x, n) free (x, n)
#else #else
# define mem_a(x) util_memory_a((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_d(x) util_memory_d((x), __LINE__, __FILE__)
# define mem_r(x, n) util_memory_r((x), (n), __LINE__, __FILE__)
#endif #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 FLT2INT(Y) *((int32_t*)&(Y))
#define INT2FLT(Y) *((float *)&(Y)) #define INT2FLT(Y) *((float *)&(Y))
/* Builds vector type (usefull for inside structures) */ /* New flexible vector implementation from Dale */
#define VECTOR_SNAP(X,Y) X ## Y #define _vec_raw(A) (((size_t*)(A)) - 2)
#define VECTOR_FILL(X,Y) VECTOR_SNAP(X,Y) #define _vec_beg(A) (_vec_raw(A)[0])
#define VECTOR_TYPE(T,N) \ #define _vec_end(A) (_vec_raw(A)[1])
T* N##_data = NULL; \ #define _vec_needsgrow(A,N) ((!(A)) || (_vec_end(A) + (N) >= _vec_beg(A)))
long N##_elements = 0; \ #define _vec_mightgrow(A,N) (_vec_needsgrow((A), (N)) ? _vec_forcegrow((A),(N)) : 0)
long N##_allocated = 0 #define _vec_forcegrow(A,N) _util_vec_grow((void**)&(A), (N), sizeof(*(A)))
/* Builds vector add */ void _util_vec_grow(void **a, size_t i, size_t s);
#define VECTOR_CORE(T,N) \ /* exposed interface */
int N##_add(T element) { \ #define vec_free(A) ((A) ? (mem_d(_vec_raw(A)), (A) = NULL) : 0)
void *temp = NULL; \ #define vec_push(A,V) (_vec_mightgrow((A),1), (A)[_vec_end(A)++] = (V))
if (N##_elements == N##_allocated) { \ #define vec_size(A) ((A) ? _vec_end(A) : 0)
if (N##_allocated == 0) { \ #define vec_add(A,N) (_vec_mightgrow((A),(N)), _vec_end(A)+=(N), &(A)[_vec_end(A)-(N)])
N##_allocated = 12; \ #define vec_last(A) ((A)[_vec_end(A)-1])
} else { \ #define vec_append(A,N,S) memcpy(vec_add((A), (N)), (S), N * sizeof(*(S)))
N##_allocated *= 2; \ #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))
if (!(temp = mem_a(N##_allocated * sizeof(T)))) { \ #define vec_pop(A) vec_remove((A), _vec_end(A)-1, 1)
mem_d(temp); \ /* these are supposed to NOT reallocate */
return -1; \ #define vec_shrinkto(A,N) (_vec_end(A) = (N))
} \ #define vec_shrinkby(A,N) (_vec_end(A) -= (N))
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)
/*===================================================================*/ /*===================================================================*/
/*=========================== code.c ================================*/ /*=========================== code.c ================================*/
@ -499,24 +479,12 @@ enum {
VINSTR_COND VINSTR_COND
}; };
/* extern prog_section_statement *code_statements;
* The symbols below are created by the following extern prog_section_def *code_defs;
* expanded macros: extern prog_section_field *code_fields;
* extern prog_section_function *code_functions;
* VECTOR_MAKE(prog_section_statement, code_statements); extern int *code_globals;
* VECTOR_MAKE(prog_section_def, code_defs ); extern char *code_chars;
* 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 uint16_t code_crc; extern uint16_t code_crc;
typedef float qcfloat; typedef float qcfloat;
@ -900,16 +868,16 @@ typedef struct {
typedef struct qc_program_s { typedef struct qc_program_s {
char *filename; char *filename;
MEM_VECTOR_MAKE(prog_section_statement, code); prog_section_statement *code;
MEM_VECTOR_MAKE(prog_section_def, defs); prog_section_def *defs;
MEM_VECTOR_MAKE(prog_section_def, fields); prog_section_def *fields;
MEM_VECTOR_MAKE(prog_section_function, functions); prog_section_function *functions;
MEM_VECTOR_MAKE(char, strings); char *strings;
MEM_VECTOR_MAKE(qcint, globals); qcint *globals;
MEM_VECTOR_MAKE(qcint, entitydata); qcint *entitydata;
MEM_VECTOR_MAKE(bool, entitypool); bool *entitypool;
MEM_VECTOR_MAKE(const char*, function_stack); const char* *function_stack;
uint16_t crc16; uint16_t crc16;
@ -918,17 +886,18 @@ typedef struct qc_program_s {
qcint vmerror; 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; */ /* size_t ip; */
qcint entities; qcint entities;
size_t entityfields; size_t entityfields;
bool allowworldwrites; bool allowworldwrites;
MEM_VECTOR_MAKE(qcint, localstack); qcint *localstack;
MEM_VECTOR_MAKE(qc_exec_stack, stack); qc_exec_stack *stack;
size_t statement; size_t statement;
size_t xflags; 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 */ /* and the output type of a function */
int outtype; int outtype;
MEM_VECTOR_MAKE(struct ir_instr_s*, reads); struct ir_instr_s **reads;
MEM_VECTOR_MAKE(struct ir_instr_s*, writes); struct ir_instr_s **writes;
/* constantvalues */ /* constantvalues */
bool isconst; bool isconst;
@ -72,7 +72,7 @@ typedef struct ir_value_s {
struct ir_value_s *memberof; struct ir_value_s *memberof;
/* For the temp allocator */ /* For the temp allocator */
MEM_VECTOR_MAKE(ir_life_entry_t, life); ir_life_entry_t *life;
} ir_value; } ir_value;
int32_t ir_value_code_addr(const 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); bool ir_value_set_name(ir_value*, const char *name);
ir_value* ir_value_vector_member(ir_value*, unsigned int member); ir_value* ir_value_vector_member(ir_value*, unsigned int member);
MEM_VECTOR_PROTO_ALL(ir_value, struct ir_instr_s*, reads); bool GMQCC_WARN vec_ir_value_find(ir_value **vec, ir_value *what, size_t *idx);
MEM_VECTOR_PROTO_ALL(ir_value, struct ir_instr_s*, writes);
bool GMQCC_WARN ir_value_set_float(ir_value*, float f); bool GMQCC_WARN ir_value_set_float(ir_value*, float f);
bool GMQCC_WARN ir_value_set_func(ir_value*, int 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_v(ir_value*, ir_value* p); */
/*bool ir_value_set_pointer_i(ir_value*, int i); */ /*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 */ /* merge an instruction into the life-range */
/* returns false if the lifepoint was already known */ /* returns false if the lifepoint was already known */
bool ir_value_life_merge(ir_value*, size_t); 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(ir_value*, int (*oprintf)(const char*,...));
void ir_value_dump_life(const ir_value *self, 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 */ /* PHI data */
typedef struct ir_phi_entry_s typedef struct ir_phi_entry_s
{ {
@ -135,8 +127,8 @@ typedef struct ir_instr_s
ir_value* (_ops[3]); ir_value* (_ops[3]);
struct ir_block_s* (bops[2]); struct ir_block_s* (bops[2]);
MEM_VECTOR_MAKE(ir_phi_entry_t, phi); ir_phi_entry_t *phi;
MEM_VECTOR_MAKE(ir_value*, params); ir_value **params;
/* For the temp-allocation */ /* For the temp-allocation */
size_t eid; size_t eid;
@ -147,10 +139,9 @@ typedef struct ir_instr_s
ir_instr* ir_instr_new(struct ir_block_s *owner, int opcode); ir_instr* ir_instr_new(struct ir_block_s *owner, int opcode);
void ir_instr_delete(ir_instr*); void ir_instr_delete(ir_instr*);
MEM_VECTOR_PROTO(ir_value, ir_phi_entry_t, phi); bool GMQCC_WARN vec_ir_instr_find(ir_instr **vec, ir_instr *what, size_t *idx);
bool GMQCC_WARN ir_instr_op(ir_instr*, int op, ir_value *value, bool writing);
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*,...)); 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; lex_ctx context;
bool final; /* once a jump is added we're done */ bool final; /* once a jump is added we're done */
MEM_VECTOR_MAKE(ir_instr*, instr); ir_instr **instr;
MEM_VECTOR_MAKE(struct ir_block_s*, entries); struct ir_block_s **entries;
MEM_VECTOR_MAKE(struct ir_block_s*, exits); struct ir_block_s **exits;
MEM_VECTOR_MAKE(ir_value*, living); ir_value **living;
/* For the temp-allocation */ /* For the temp-allocation */
size_t eid; size_t eid;
@ -182,10 +173,6 @@ void ir_block_delete(ir_block*);
bool ir_block_set_label(ir_block*, const char *label); 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* ir_block_create_binop(ir_block*, const char *label, int op,
ir_value *left, ir_value *right); ir_value *left, ir_value *right);
ir_value* ir_block_create_unary(ir_block*, const char *label, int op, 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_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_instr* ir_block_create_phi(ir_block*, const char *label, int vtype);
ir_value* ir_phi_value(ir_instr*); 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_instr* ir_block_create_call(ir_block*, const char *label, ir_value *func);
ir_value* ir_call_value(ir_instr*); 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); 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_jump(ir_block*, ir_block *to);
bool GMQCC_WARN ir_block_create_goto(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*,...)); void ir_block_dump(ir_block*, char *ind, int (*oprintf)(const char*,...));
/* function */ /* function */
@ -239,8 +224,8 @@ typedef struct ir_function_s
{ {
char *name; char *name;
int outtype; int outtype;
MEM_VECTOR_MAKE(int, params); int *params;
MEM_VECTOR_MAKE(ir_block*, blocks); ir_block **blocks;
int builtin; int builtin;
@ -250,10 +235,10 @@ typedef struct ir_function_s
* which might get optimized away, so anything * which might get optimized away, so anything
* in there needs to be deleted in the dtor. * in there needs to be deleted in the dtor.
*/ */
MEM_VECTOR_MAKE(ir_value*, values); ir_value **values;
/* locally defined variables */ /* locally defined variables */
MEM_VECTOR_MAKE(ir_value*, locals); ir_value **locals;
size_t allocated_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); ir_function* ir_function_new(struct ir_builder_s *owner, int returntype);
void ir_function_delete(ir_function*); 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); 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_get_local(ir_function *self, const char *name);
ir_value* ir_function_create_local(ir_function *self, const char *name, int vtype, bool param); 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 typedef struct ir_builder_s
{ {
char *name; char *name;
MEM_VECTOR_MAKE(ir_function*, functions); ir_function **functions;
MEM_VECTOR_MAKE(ir_value*, globals); ir_value **globals;
MEM_VECTOR_MAKE(ir_value*, fields); ir_value **fields;
MEM_VECTOR_MAKE(const char*, filenames); const char **filenames;
MEM_VECTOR_MAKE(qcint, filestrings); qcint *filestrings;
/* we cache the #IMMEDIATE string here */ /* we cache the #IMMEDIATE string here */
qcint str_immediate; qcint str_immediate;
} ir_builder; } ir_builder;
@ -318,12 +301,6 @@ void ir_builder_delete(ir_builder*);
bool ir_builder_set_name(ir_builder *self, const char *name); 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_get_function(ir_builder*, const char *fun);
ir_function* ir_builder_create_function(ir_builder*, const char *name, int outtype); 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(token, char, value)
MEM_VEC_FUNCTIONS(lex_file, frame_macro, frames) MEM_VEC_FUNCTIONS(lex_file, frame_macro, frames)
VECTOR_MAKE(char*, lex_filenames); char* *lex_filenames;
void lexerror(lex_file *lex, const char *fmt, ...) void lexerror(lex_file *lex, const char *fmt, ...)
{ {
@ -157,8 +157,7 @@ lex_file* lex_open(const char *file)
lex->peekpos = 0; lex->peekpos = 0;
lex->eof = false; lex->eof = false;
lex_filenames_add(lex->name); vec_push(lex_filenames, lex->name);
return lex; return lex;
} }
@ -185,7 +184,7 @@ lex_file* lex_open_string(const char *str, size_t len, const char *name)
lex->peekpos = 0; lex->peekpos = 0;
lex->eof = false; lex->eof = false;
lex_filenames_add(lex->name); vec_push(lex_filenames, lex->name);
return lex; return lex;
} }
@ -193,9 +192,9 @@ lex_file* lex_open_string(const char *str, size_t len, const char *name)
void lex_cleanup(void) void lex_cleanup(void)
{ {
size_t i; size_t i;
for (i = 0; i < lex_filenames_elements; ++i) for (i = 0; i < vec_size(lex_filenames); ++i)
mem_d(lex_filenames_data[i]); mem_d(lex_filenames[i]);
mem_d(lex_filenames_data); vec_free(lex_filenames);
} }
void lex_close(lex_file *lex) 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; size_t operator_count = 0;
typedef struct { char *filename; int type; } argitem; typedef struct { char *filename; int type; } argitem;
VECTOR_MAKE(argitem, items); static argitem *items = NULL;
#define TYPE_QC 0 #define TYPE_QC 0
#define TYPE_ASM 1 #define TYPE_ASM 1
@ -341,7 +341,7 @@ static bool options_parse(int argc, char **argv) {
return false; return false;
} }
item.filename = argarg; item.filename = argarg;
items_add(item); vec_push(items, item);
break; break;
case '-': case '-':
@ -378,7 +378,7 @@ static bool options_parse(int argc, char **argv) {
argitem item; argitem item;
item.filename = argv[0]; item.filename = argv[0];
item.type = TYPE_QC; item.type = TYPE_QC;
items_add(item); vec_push(items, item);
} }
} }
con_change(redirout, redirerr); con_change(redirout, redirerr);
@ -471,18 +471,18 @@ int main(int argc, char **argv) {
util_debug("COM", "starting ...\n"); util_debug("COM", "starting ...\n");
if (items_elements) { if (vec_size(items)) {
con_out("Mode: manual\n"); con_out("Mode: manual\n");
con_out("There are %lu items to compile:\n", (unsigned long)items_elements); con_out("There are %lu items to compile:\n", (unsigned long)vec_size(items));
for (itr = 0; itr < items_elements; ++itr) { for (itr = 0; itr < vec_size(items); ++itr) {
con_out(" item: %s (%s)\n", con_out(" item: %s (%s)\n",
items_data[itr].filename, items[itr].filename,
( (items_data[itr].type == TYPE_QC ? "qc" : ( (items[itr].type == TYPE_QC ? "qc" :
(items_data[itr].type == TYPE_ASM ? "asm" : (items[itr].type == TYPE_ASM ? "asm" :
(items_data[itr].type == TYPE_SRC ? "progs.src" : (items[itr].type == TYPE_SRC ? "progs.src" :
("unknown")))))); ("unknown"))))));
if (!parser_compile_file(items_data[itr].filename)) if (!parser_compile_file(items[itr].filename))
{ {
retval = 1; retval = 1;
goto cleanup; goto cleanup;
@ -541,7 +541,7 @@ srcdone:
cleanup: cleanup:
util_debug("COM", "cleaning ...\n"); util_debug("COM", "cleaning ...\n");
con_close(); con_close();
mem_d(items_data); vec_free(items);
parser_cleanup(); parser_cleanup();
if (opts_output_free) 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 { struct memblock_t {
const char *file; const char *file;
unsigned int line; unsigned int line;
unsigned int byte; size_t byte;
struct memblock_t *next; struct memblock_t *next;
struct memblock_t *prev; struct memblock_t *prev;
}; };
static struct memblock_t *mem_start = NULL; 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); struct memblock_t *info = malloc(sizeof(struct memblock_t) + byte);
void *data = (void*)(info+1); void *data = (void*)(info+1);
if (!info) return NULL; if (!info) return NULL;
@ -79,7 +79,7 @@ void util_memory_d(void *ptrn, unsigned int line, const char *file) {
free(info); 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 *oldinfo = NULL;
struct memblock_t *newinfo; 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->file = file;
newinfo->next = oldinfo->next; newinfo->next = oldinfo->next;
newinfo->prev = oldinfo->prev; newinfo->prev = oldinfo->prev;
if (newinfo->next)
newinfo->next->prev = newinfo;
if (newinfo->prev)
newinfo->prev->next = newinfo;
if (mem_start == oldinfo) if (mem_start == oldinfo)
mem_start = newinfo; mem_start = newinfo;
@ -511,3 +515,11 @@ FILE *util_fopen(const char *filename, const char *mode)
#endif #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;
}