mirror of
https://github.com/DarkPlacesEngine/gmqcc.git
synced 2025-01-31 03:50:36 +00:00
don't just store a 'bool constant' in the ast/ir, store the complete qualifier: 'int cvq', moved CV_ defines into gmqcc.h
This commit is contained in:
parent
8e043c8447
commit
5e23e8296d
6 changed files with 47 additions and 43 deletions
2
ast.c
2
ast.c
|
@ -322,7 +322,7 @@ ast_value* ast_value_new(lex_ctx ctx, const char *name, int t)
|
|||
self->name = name ? util_strdup(name) : NULL;
|
||||
self->expression.vtype = t;
|
||||
self->expression.next = NULL;
|
||||
self->constant = false;
|
||||
self->cvq = CV_NONE;
|
||||
self->hasvalue = false;
|
||||
self->uses = 0;
|
||||
memset(&self->constval, 0, sizeof(self->constval));
|
||||
|
|
2
ast.h
2
ast.h
|
@ -159,7 +159,7 @@ struct ast_value_s
|
|||
ast_value *next;
|
||||
*/
|
||||
|
||||
bool constant;
|
||||
bool cvq; /* const/var qualifier */
|
||||
bool hasvalue;
|
||||
union {
|
||||
double vfloat;
|
||||
|
|
5
gmqcc.h
5
gmqcc.h
|
@ -328,6 +328,11 @@ enum {
|
|||
TYPE_COUNT
|
||||
};
|
||||
|
||||
/* const/var qualifiers */
|
||||
#define CV_NONE 0
|
||||
#define CV_CONST 1
|
||||
#define CV_VAR -1
|
||||
|
||||
extern const char *type_name[TYPE_COUNT];
|
||||
|
||||
extern size_t type_sizeof[TYPE_COUNT];
|
||||
|
|
37
ir.c
37
ir.c
|
@ -361,7 +361,7 @@ ir_function* ir_builder_create_function(ir_builder *self, const char *name, int
|
|||
return NULL;
|
||||
}
|
||||
|
||||
fn->value->isconst = true;
|
||||
fn->value->hasvalue = true;
|
||||
fn->value->outtype = outtype;
|
||||
fn->value->constval.vfunc = fn;
|
||||
fn->value->context = fn->context;
|
||||
|
@ -841,7 +841,8 @@ ir_value* ir_value_var(const char *name, int storetype, int vtype)
|
|||
self->reads = NULL;
|
||||
self->writes = NULL;
|
||||
|
||||
self->isconst = false;
|
||||
self->cvq = CV_NONE;
|
||||
self->hasvalue = false;
|
||||
self->context.file = "<@no context>";
|
||||
self->context.line = 0;
|
||||
self->name = NULL;
|
||||
|
@ -919,7 +920,7 @@ void ir_value_delete(ir_value* self)
|
|||
size_t i;
|
||||
if (self->name)
|
||||
mem_d((void*)self->name);
|
||||
if (self->isconst)
|
||||
if (self->hasvalue)
|
||||
{
|
||||
if (self->vtype == TYPE_STRING)
|
||||
mem_d((void*)self->constval.vstring);
|
||||
|
@ -947,7 +948,7 @@ bool ir_value_set_float(ir_value *self, float f)
|
|||
if (self->vtype != TYPE_FLOAT)
|
||||
return false;
|
||||
self->constval.vfloat = f;
|
||||
self->isconst = true;
|
||||
self->hasvalue = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -956,7 +957,7 @@ bool ir_value_set_func(ir_value *self, int f)
|
|||
if (self->vtype != TYPE_FUNCTION)
|
||||
return false;
|
||||
self->constval.vint = f;
|
||||
self->isconst = true;
|
||||
self->hasvalue = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -965,7 +966,7 @@ bool ir_value_set_vector(ir_value *self, vector v)
|
|||
if (self->vtype != TYPE_VECTOR)
|
||||
return false;
|
||||
self->constval.vvec = v;
|
||||
self->isconst = true;
|
||||
self->hasvalue = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -974,7 +975,7 @@ bool ir_value_set_field(ir_value *self, ir_value *fld)
|
|||
if (self->vtype != TYPE_FIELD)
|
||||
return false;
|
||||
self->constval.vpointer = fld;
|
||||
self->isconst = true;
|
||||
self->hasvalue = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -994,7 +995,7 @@ bool ir_value_set_string(ir_value *self, const char *str)
|
|||
if (self->vtype != TYPE_STRING)
|
||||
return false;
|
||||
self->constval.vstring = ir_strdup(str);
|
||||
self->isconst = true;
|
||||
self->hasvalue = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1004,7 +1005,7 @@ bool ir_value_set_int(ir_value *self, int i)
|
|||
if (self->vtype != TYPE_INTEGER)
|
||||
return false;
|
||||
self->constval.vint = i;
|
||||
self->isconst = true;
|
||||
self->hasvalue = true;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
@ -2440,7 +2441,7 @@ static bool ir_builder_gen_global(ir_builder *self, ir_value *global, bool isloc
|
|||
|
||||
static bool gen_global_field(ir_value *global)
|
||||
{
|
||||
if (global->isconst)
|
||||
if (global->hasvalue)
|
||||
{
|
||||
ir_value *fld = global->constval.vpointer;
|
||||
if (!fld) {
|
||||
|
@ -2485,7 +2486,7 @@ static bool gen_global_field(ir_value *global)
|
|||
|
||||
static bool gen_global_pointer(ir_value *global)
|
||||
{
|
||||
if (global->isconst)
|
||||
if (global->hasvalue)
|
||||
{
|
||||
ir_value *target = global->constval.vpointer;
|
||||
if (!target) {
|
||||
|
@ -2825,7 +2826,7 @@ static bool gen_global_function(ir_builder *ir, ir_value *global)
|
|||
size_t i;
|
||||
size_t local_var_end;
|
||||
|
||||
if (!global->isconst || (!global->constval.vfunc))
|
||||
if (!global->hasvalue || (!global->constval.vfunc))
|
||||
{
|
||||
irerror(global->context, "Invalid state of function-global: not constant: %s", global->name);
|
||||
return false;
|
||||
|
@ -3035,7 +3036,7 @@ static bool ir_builder_gen_global(ir_builder *self, ir_value *global, bool isloc
|
|||
case TYPE_FLOAT:
|
||||
{
|
||||
ir_value_code_setaddr(global, vec_size(code_globals));
|
||||
if (global->isconst) {
|
||||
if (global->hasvalue) {
|
||||
iptr = (int32_t*)&global->constval.ivec[0];
|
||||
vec_push(code_globals, *iptr);
|
||||
} else {
|
||||
|
@ -3050,7 +3051,7 @@ static bool ir_builder_gen_global(ir_builder *self, ir_value *global, bool isloc
|
|||
case TYPE_STRING:
|
||||
{
|
||||
ir_value_code_setaddr(global, vec_size(code_globals));
|
||||
if (global->isconst) {
|
||||
if (global->hasvalue) {
|
||||
vec_push(code_globals, code_genstring(global->constval.vstring));
|
||||
} else {
|
||||
vec_push(code_globals, 0);
|
||||
|
@ -3064,7 +3065,7 @@ static bool ir_builder_gen_global(ir_builder *self, ir_value *global, bool isloc
|
|||
{
|
||||
size_t d;
|
||||
ir_value_code_setaddr(global, vec_size(code_globals));
|
||||
if (global->isconst) {
|
||||
if (global->hasvalue) {
|
||||
iptr = (int32_t*)&global->constval.ivec[0];
|
||||
vec_push(code_globals, iptr[0]);
|
||||
if (global->code.globaladdr < 0)
|
||||
|
@ -3090,7 +3091,7 @@ static bool ir_builder_gen_global(ir_builder *self, ir_value *global, bool isloc
|
|||
}
|
||||
case TYPE_FUNCTION:
|
||||
ir_value_code_setaddr(global, vec_size(code_globals));
|
||||
if (!global->isconst) {
|
||||
if (!global->hasvalue) {
|
||||
vec_push(code_globals, 0);
|
||||
if (global->code.globaladdr < 0)
|
||||
return false;
|
||||
|
@ -3268,7 +3269,7 @@ void ir_builder_dump(ir_builder *b, int (*oprintf)(const char*, ...))
|
|||
for (i = 0; i < vec_size(b->globals); ++i)
|
||||
{
|
||||
oprintf("global ");
|
||||
if (b->globals[i]->isconst)
|
||||
if (b->globals[i]->hasvalue)
|
||||
oprintf("%s = ", b->globals[i]->name);
|
||||
ir_value_dump(b->globals[i], oprintf);
|
||||
oprintf("\n");
|
||||
|
@ -3435,7 +3436,7 @@ void ir_value_dump_string(const char *str, int (*oprintf)(const char*, ...))
|
|||
|
||||
void ir_value_dump(ir_value* v, int (*oprintf)(const char*, ...))
|
||||
{
|
||||
if (v->isconst) {
|
||||
if (v->hasvalue) {
|
||||
switch (v->vtype) {
|
||||
default:
|
||||
case TYPE_VOID:
|
||||
|
|
4
ir.h
4
ir.h
|
@ -42,12 +42,14 @@ typedef struct ir_value_s {
|
|||
int fieldtype;
|
||||
/* and the output type of a function */
|
||||
int outtype;
|
||||
/* 'const' vs 'var' qualifier */
|
||||
int cvq;
|
||||
|
||||
struct ir_instr_s **reads;
|
||||
struct ir_instr_s **writes;
|
||||
|
||||
/* constantvalues */
|
||||
bool isconst;
|
||||
bool hasvalue;
|
||||
union {
|
||||
float vfloat;
|
||||
int vint;
|
||||
|
|
40
parser.c
40
parser.c
|
@ -88,10 +88,6 @@ typedef struct {
|
|||
qcint memberof;
|
||||
} parser_t;
|
||||
|
||||
#define CV_NONE 0
|
||||
#define CV_CONST 1
|
||||
#define CV_VAR -1
|
||||
|
||||
static void parser_enterblock(parser_t *parser);
|
||||
static bool parser_leaveblock(parser_t *parser);
|
||||
static void parser_addlocal(parser_t *parser, const char *name, ast_expression *e);
|
||||
|
@ -221,7 +217,7 @@ static ast_value* parser_const_float(parser_t *parser, double d)
|
|||
return parser->imm_float[i];
|
||||
}
|
||||
out = ast_value_new(parser_ctx(parser), "#IMMEDIATE", TYPE_FLOAT);
|
||||
out->constant = true;
|
||||
out->cvq = CV_CONST;
|
||||
out->hasvalue = true;
|
||||
out->constval.vfloat = d;
|
||||
vec_push(parser->imm_float, out);
|
||||
|
@ -267,7 +263,7 @@ static ast_value* parser_const_string(parser_t *parser, const char *str, bool do
|
|||
out = ast_value_new(parser_ctx(parser), name, TYPE_STRING);
|
||||
} else
|
||||
out = ast_value_new(parser_ctx(parser), "#IMMEDIATE", TYPE_STRING);
|
||||
out->constant = true;
|
||||
out->cvq = CV_CONST;
|
||||
out->hasvalue = true;
|
||||
out->constval.vstring = parser_strdup(str);
|
||||
vec_push(parser->imm_string, out);
|
||||
|
@ -283,7 +279,7 @@ static ast_value* parser_const_vector(parser_t *parser, vector v)
|
|||
return parser->imm_vector[i];
|
||||
}
|
||||
out = ast_value_new(parser_ctx(parser), "#IMMEDIATE", TYPE_VECTOR);
|
||||
out->constant = true;
|
||||
out->cvq = CV_CONST;
|
||||
out->hasvalue = true;
|
||||
out->constval.vvec = v;
|
||||
vec_push(parser->imm_vector, out);
|
||||
|
@ -531,7 +527,7 @@ static bool parser_sy_pop(parser_t *parser, shunt *sy)
|
|||
(exprs[0]->expression.vtype != exprs[1]->expression.vtype || \
|
||||
exprs[0]->expression.vtype != T)
|
||||
#define CanConstFold1(A) \
|
||||
(ast_istype((A), ast_value) && ((ast_value*)(A))->hasvalue && ((ast_value*)(A))->constant)
|
||||
(ast_istype((A), ast_value) && ((ast_value*)(A))->hasvalue && (((ast_value*)(A))->cvq == CV_CONST))
|
||||
#define CanConstFold(A, B) \
|
||||
(CanConstFold1(A) && CanConstFold1(B))
|
||||
#define ConstV(i) (asvalue[(i)]->constval.vvec)
|
||||
|
@ -954,7 +950,7 @@ static bool parser_sy_pop(parser_t *parser, shunt *sy)
|
|||
parseerror(parser, "invalid types in assignment: cannot assign %s to %s", ty2, ty1);
|
||||
}
|
||||
}
|
||||
if (ast_istype(exprs[0], ast_value) && asvalue[0]->constant) {
|
||||
if (ast_istype(exprs[0], ast_value) && asvalue[0]->cvq == CV_CONST) {
|
||||
parseerror(parser, "assignment to constant `%s`", asvalue[0]->name);
|
||||
}
|
||||
out = (ast_expression*)ast_store_new(ctx, assignop, exprs[0], exprs[1]);
|
||||
|
@ -971,7 +967,7 @@ static bool parser_sy_pop(parser_t *parser, shunt *sy)
|
|||
addop = INSTR_ADD_F;
|
||||
else
|
||||
addop = INSTR_SUB_F;
|
||||
if (ast_istype(exprs[0], ast_value) && asvalue[0]->constant) {
|
||||
if (ast_istype(exprs[0], ast_value) && asvalue[0]->cvq == CV_CONST) {
|
||||
parseerror(parser, "assignment to constant `%s`", asvalue[0]->name);
|
||||
}
|
||||
if (ast_istype(exprs[0], ast_entfield)) {
|
||||
|
@ -999,7 +995,7 @@ static bool parser_sy_pop(parser_t *parser, shunt *sy)
|
|||
addop = INSTR_SUB_F;
|
||||
subop = INSTR_ADD_F;
|
||||
}
|
||||
if (ast_istype(exprs[0], ast_value) && asvalue[0]->constant) {
|
||||
if (ast_istype(exprs[0], ast_value) && asvalue[0]->cvq == CV_CONST) {
|
||||
parseerror(parser, "assignment to constant `%s`", asvalue[0]->name);
|
||||
}
|
||||
if (ast_istype(exprs[0], ast_entfield)) {
|
||||
|
@ -1028,7 +1024,7 @@ static bool parser_sy_pop(parser_t *parser, shunt *sy)
|
|||
ty1, ty2);
|
||||
return false;
|
||||
}
|
||||
if (ast_istype(exprs[0], ast_value) && asvalue[0]->constant) {
|
||||
if (ast_istype(exprs[0], ast_value) && asvalue[0]->cvq == CV_CONST) {
|
||||
parseerror(parser, "assignment to constant `%s`", asvalue[0]->name);
|
||||
}
|
||||
if (ast_istype(exprs[0], ast_entfield))
|
||||
|
@ -1065,7 +1061,7 @@ static bool parser_sy_pop(parser_t *parser, shunt *sy)
|
|||
ty1, ty2);
|
||||
return false;
|
||||
}
|
||||
if (ast_istype(exprs[0], ast_value) && asvalue[0]->constant) {
|
||||
if (ast_istype(exprs[0], ast_value) && asvalue[0]->cvq == CV_CONST) {
|
||||
parseerror(parser, "assignment to constant `%s`", asvalue[0]->name);
|
||||
}
|
||||
if (ast_istype(exprs[0], ast_entfield))
|
||||
|
@ -1109,7 +1105,7 @@ static bool parser_sy_pop(parser_t *parser, shunt *sy)
|
|||
ty1, ty2);
|
||||
return false;
|
||||
}
|
||||
if (ast_istype(exprs[0], ast_value) && asvalue[0]->constant) {
|
||||
if (ast_istype(exprs[0], ast_value) && asvalue[0]->cvq == CV_CONST) {
|
||||
parseerror(parser, "assignment to constant `%s`", asvalue[0]->name);
|
||||
}
|
||||
if (ast_istype(exprs[0], ast_entfield))
|
||||
|
@ -1139,7 +1135,7 @@ static bool parser_sy_pop(parser_t *parser, shunt *sy)
|
|||
out = (ast_expression*)ast_binary_new(ctx, INSTR_BITAND, exprs[0], exprs[1]);
|
||||
if (!out)
|
||||
return false;
|
||||
if (ast_istype(exprs[0], ast_value) && asvalue[0]->constant) {
|
||||
if (ast_istype(exprs[0], ast_value) && asvalue[0]->cvq == CV_CONST) {
|
||||
parseerror(parser, "assignment to constant `%s`", asvalue[0]->name);
|
||||
}
|
||||
asbinstore = ast_binstore_new(ctx, assignop, INSTR_SUB_F, exprs[0], out);
|
||||
|
@ -2166,7 +2162,7 @@ static bool parse_switch(parser_t *parser, ast_block *block, ast_expression **ou
|
|||
}
|
||||
if (!OPTS_FLAG(RELAXED_SWITCH)) {
|
||||
opval = (ast_value*)swcase.value;
|
||||
if (!ast_istype(swcase.value, ast_value)) { /* || !opval->constant) { */
|
||||
if (!ast_istype(swcase.value, ast_value)) { /* || opval->cvq != CV_CONST) { */
|
||||
parseerror(parser, "case on non-constant values need to be explicitly enabled via -frelaxed-switch");
|
||||
ast_unref(operand);
|
||||
return false;
|
||||
|
@ -3630,7 +3626,7 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield
|
|||
}
|
||||
|
||||
if (is_const_var == CV_CONST)
|
||||
var->constant = true;
|
||||
var->cvq = CV_CONST;
|
||||
|
||||
/* Part 1:
|
||||
* check for validity: (end_sys_..., multiple-definitions, prototypes, ...)
|
||||
|
@ -3997,7 +3993,7 @@ skipvar:
|
|||
|
||||
if (!localblock) {
|
||||
cval = (ast_value*)cexp;
|
||||
if (!ast_istype(cval, ast_value) || !cval->hasvalue || !cval->constant)
|
||||
if (!ast_istype(cval, ast_value) || !cval->hasvalue || cval->cvq != CV_CONST)
|
||||
parseerror(parser, "cannot initialize a global constant variable with a non-constant expression");
|
||||
else
|
||||
{
|
||||
|
@ -4005,7 +4001,7 @@ skipvar:
|
|||
!OPTS_FLAG(INITIALIZED_NONCONSTANTS) &&
|
||||
is_const_var != CV_VAR)
|
||||
{
|
||||
var->constant = true;
|
||||
var->cvq = CV_CONST;
|
||||
}
|
||||
var->hasvalue = true;
|
||||
if (cval->expression.vtype == TYPE_STRING)
|
||||
|
@ -4017,8 +4013,8 @@ skipvar:
|
|||
} else {
|
||||
bool cvq;
|
||||
shunt sy = { NULL, NULL };
|
||||
cvq = var->constant;
|
||||
var->constant = false;
|
||||
cvq = var->cvq;
|
||||
var->cvq = CV_NONE;
|
||||
vec_push(sy.out, syexp(ast_ctx(var), (ast_expression*)var));
|
||||
vec_push(sy.out, syexp(ast_ctx(cexp), (ast_expression*)cexp));
|
||||
vec_push(sy.ops, syop(ast_ctx(var), parser->assign_op));
|
||||
|
@ -4031,7 +4027,7 @@ skipvar:
|
|||
}
|
||||
vec_free(sy.out);
|
||||
vec_free(sy.ops);
|
||||
var->constant = cvq;
|
||||
var->cvq = cvq;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue