compile_error(ctx, "arithmetic overflow in `%s' component", vec);
if (state->exceptionflags & SFLOAT_UNDERFLOW)
compile_error(ctx, "arithmetic underflow in `%s' component", vec);
- return;
+ return;
}
if (state->exceptionflags & SFLOAT_DIVBYZERO)
compile_error(ctx, "division by zero");
* This file is thus, split into two parts.
*/
-#define isfloat(X) (((ast_expression*)(X))->vtype == TYPE_FLOAT)
-#define isvector(X) (((ast_expression*)(X))->vtype == TYPE_VECTOR)
-#define isstring(X) (((ast_expression*)(X))->vtype == TYPE_STRING)
-#define isarray(X) (((ast_expression*)(X))->vtype == TYPE_ARRAY)
+#define isfloat(X) (((X))->m_vtype == TYPE_FLOAT)
+#define isvector(X) (((X))->m_vtype == TYPE_VECTOR)
+#define isstring(X) (((X))->m_vtype == TYPE_STRING)
+#define isarray(X) (((X))->m_vtype == TYPE_ARRAY)
#define isfloats(X,Y) (isfloat (X) && isfloat (Y))
/*
}
qcfloat_t fold::immvalue_float(ast_value *value) {
- return value->constval.vfloat;
+ return value->m_constval.vfloat;
}
vec3_t fold::immvalue_vector(ast_value *value) {
- return value->constval.vvec;
+ return value->m_constval.vvec;
}
const char *fold::immvalue_string(ast_value *value) {
- return value->constval.vstring;
+ return value->m_constval.vstring;
}
lex_ctx_t fold::ctx() {
}
bool fold::immediate_true(ast_value *v) {
- switch (v->expression.vtype) {
+ switch (v->m_vtype) {
case TYPE_FLOAT:
- return !!v->constval.vfloat;
+ return !!v->m_constval.vfloat;
case TYPE_INTEGER:
- return !!v->constval.vint;
+ return !!v->m_constval.vint;
case TYPE_VECTOR:
if (OPTS_FLAG(CORRECT_LOGIC))
- return vec3_pbool(v->constval.vvec);
- return !!(v->constval.vvec.x);
+ return vec3_pbool(v->m_constval.vvec);
+ return !!(v->m_constval.vvec.x);
case TYPE_STRING:
- if (!v->constval.vstring)
+ if (!v->m_constval.vstring)
return false;
if (OPTS_FLAG(TRUE_EMPTY_STRINGS))
return true;
- return !!v->constval.vstring[0];
+ return !!v->m_constval.vstring[0];
default:
compile_error(ctx(), "internal error: fold_immediate_true on invalid type");
break;
}
- return !!v->constval.vfunc;
+ return !!v->m_constval.vfunc;
}
/* Handy macros to determine if an ast_value can be constant folded. */
#define fold_can_1(X) \
- (ast_istype(((ast_expression*)(X)), ast_value) && (X)->hasvalue && ((X)->cvq == CV_CONST) && \
- ((ast_expression*)(X))->vtype != TYPE_FUNCTION)
+ (ast_istype(((X)), ast_value) && (X)->m_hasvalue && ((X)->m_cvq == CV_CONST) && \
+ ((X))->m_vtype != TYPE_FUNCTION)
#define fold_can_2(X, Y) (fold_can_1(X) && fold_can_1(Y))
// generate globals for immediate folded values
ast_value *cur;
for (auto &it : m_imm_float)
- if (!ast_global_codegen((cur = it), ir, false)) goto err;
+ if (!(cur = it)->generateGlobal(ir, false)) goto err;
for (auto &it : m_imm_vector)
- if (!ast_global_codegen((cur = it), ir, false)) goto err;
+ if (!(cur = it)->generateGlobal(ir, false)) goto err;
for (auto &it : m_imm_string)
- if (!ast_global_codegen((cur = it), ir, false)) goto err;
+ if (!(cur = it)->generateGlobal(ir, false)) goto err;
return true;
err:
- con_out("failed to generate global %s\n", cur->name);
- ir_builder_delete(ir);
+ con_out("failed to generate global %s\n", cur->m_name.c_str());
+ delete ir;
return false;
}
ast_expression *fold::constgen_float(qcfloat_t value, bool inexact) {
for (auto &it : m_imm_float)
- if (!memcmp(&it->constval.vfloat, &value, sizeof(qcfloat_t)))
- return (ast_expression*)it;
+ if (!memcmp(&it->m_constval.vfloat, &value, sizeof(qcfloat_t)))
+ return it;
- ast_value *out = ast_value_new(ctx(), "#IMMEDIATE", TYPE_FLOAT);
- out->cvq = CV_CONST;
- out->hasvalue = true;
- out->inexact = inexact;
- out->constval.vfloat = value;
+ ast_value *out = new ast_value(ctx(), "#IMMEDIATE", TYPE_FLOAT);
+ out->m_cvq = CV_CONST;
+ out->m_hasvalue = true;
+ out->m_inexact = inexact;
+ out->m_constval.vfloat = value;
m_imm_float.push_back(out);
- return (ast_expression*)out;
+ return out;
}
ast_expression *fold::constgen_vector(vec3_t value) {
for (auto &it : m_imm_vector)
- if (vec3_cmp(it->constval.vvec, value))
- return (ast_expression*)it;
+ if (vec3_cmp(it->m_constval.vvec, value))
+ return it;
- ast_value *out = ast_value_new(ctx(), "#IMMEDIATE", TYPE_VECTOR);
- out->cvq = CV_CONST;
- out->hasvalue = true;
- out->constval.vvec = value;
+ ast_value *out = new ast_value(ctx(), "#IMMEDIATE", TYPE_VECTOR);
+ out->m_cvq = CV_CONST;
+ out->m_hasvalue = true;
+ out->m_constval.vvec = value;
m_imm_vector.push_back(out);
- return (ast_expression*)out;
+ return out;
}
ast_expression *fold::constgen_string(const char *str, bool translate) {
size_t hash = util_hthash(table, str);
if ((out = (ast_value*)util_htgeth(table, str, hash)))
- return (ast_expression*)out;
+ return out;
if (translate) {
char name[32];
util_snprintf(name, sizeof(name), "dotranslate_%zu", m_parser->translated++);
- out = ast_value_new(ctx(), name, TYPE_STRING);
- out->expression.flags |= AST_FLAG_INCLUDE_DEF; /* def needs to be included for translatables */
+ out = new ast_value(ctx(), name, TYPE_STRING);
+ out->m_flags |= AST_FLAG_INCLUDE_DEF; /* def needs to be included for translatables */
} else {
- out = ast_value_new(ctx(), "#IMMEDIATE", TYPE_STRING);
+ out = new ast_value(ctx(), "#IMMEDIATE", TYPE_STRING);
}
- out->cvq = CV_CONST;
- out->hasvalue = true;
- out->isimm = true;
- out->constval.vstring = parser_strdup(str);
+ out->m_cvq = CV_CONST;
+ out->m_hasvalue = true;
+ out->m_isimm = true;
+ out->m_constval.vstring = parser_strdup(str);
m_imm_string.push_back(out);
util_htseth(table, str, hash, out);
- return (ast_expression*)out;
+ return out;
+}
+
+ast_expression *fold::constgen_string(const std::string &str, bool translate) {
+ return constgen_string(str.c_str(), translate);
}
typedef union {
bool fold::check_inexact_float(ast_value *a, ast_value *b) {
if (!OPTS_WARN(WARN_INEXACT_COMPARES))
return false;
- if (!a->inexact && !b->inexact)
+ if (!a->m_inexact && !b->m_inexact)
return false;
return compile_warning(ctx(), WARN_INEXACT_COMPARES, "inexact value in comparison");
}
if (!y && !z) {
ast_expression *out;
++opts_optimizationcount[OPTIM_VECTOR_COMPONENTS];
- out = (ast_expression*)ast_member_new(ctx(), (ast_expression*)sel, set[0]-'x', nullptr);
- out->node.keep = false;
- ((ast_member*)out)->rvalue = true;
+ out = ast_member::make(ctx(), sel, set[0]-'x', "");
+ out->m_keep_node = false;
+ ((ast_member*)out)->m_rvalue = true;
if (x != -1.0f)
- return (ast_expression*)ast_binary_new(ctx(), INSTR_MUL_F, constgen_float(x, false), out);
+ return new ast_binary(ctx(), INSTR_MUL_F, constgen_float(x, false), out);
}
return nullptr;
}
bool inexact = check_except_float(&sfloat_div, a, b);
return constgen_float(immvalue_float(a) / immvalue_float(b), inexact);
} else if (fold_can_1(b)) {
- return (ast_expression*)ast_binary_new(
+ return new ast_binary(
ctx(),
INSTR_MUL_F,
- (ast_expression*)a,
+ a,
constgen_float(1.0f / immvalue_float(b), false)
);
}
if (fold_can_2(a, b)) {
return constgen_vector(vec3_mulvf(ctx(), immvalue_vector(a), 1.0f / immvalue_float(b)));
} else {
- return (ast_expression*)ast_binary_new(
+ return new ast_binary(
ctx(),
INSTR_MUL_VF,
- (ast_expression*)a,
+ a,
(fold_can_1(b))
- ? (ast_expression*)constgen_float(1.0f / immvalue_float(b), false)
- : (ast_expression*)ast_binary_new(
- ctx(),
- INSTR_DIV_F,
- (ast_expression*)m_imm_float[1],
- (ast_expression*)b
+ ? constgen_float(1.0f / immvalue_float(b), false)
+ : new ast_binary(ctx(),
+ INSTR_DIV_F,
+ m_imm_float[1],
+ b
)
);
}
if (fold_can_2(a, b)) {
if (OPTS_FLAG(PERL_LOGIC)) {
if (expr)
- return immediate_true(a) ? (ast_expression*)a : (ast_expression*)b;
+ return immediate_true(a) ? a : b;
else
- return immediate_true(a) ? (ast_expression*)b : (ast_expression*)a;
+ return immediate_true(a) ? b : a;
} else {
return constgen_float(
((expr) ? (immediate_true(a) || immediate_true(b))
ast_expression *fold::op_tern(ast_value *a, ast_value *b, ast_value *c) {
if (fold_can_1(a)) {
return immediate_true(a)
- ? (ast_expression*)b
- : (ast_expression*)c;
+ ? b
+ : c;
}
return nullptr;
}
ast_expression *fold::op_lteqgt(ast_value *a, ast_value *b) {
if (fold_can_2(a,b)) {
check_inexact_float(a, b);
- if (immvalue_float(a) < immvalue_float(b)) return (ast_expression*)m_imm_float[2];
- if (immvalue_float(a) == immvalue_float(b)) return (ast_expression*)m_imm_float[0];
- if (immvalue_float(a) > immvalue_float(b)) return (ast_expression*)m_imm_float[1];
+ if (immvalue_float(a) < immvalue_float(b)) return m_imm_float[2];
+ if (immvalue_float(a) == immvalue_float(b)) return m_imm_float[0];
+ if (immvalue_float(a) > immvalue_float(b)) return m_imm_float[1];
}
return nullptr;
}
ast_expression *fold::op_ltgt(ast_value *a, ast_value *b, bool lt) {
if (fold_can_2(a, b)) {
check_inexact_float(a, b);
- return (lt) ? (ast_expression*)m_imm_float[!!(immvalue_float(a) < immvalue_float(b))]
- : (ast_expression*)m_imm_float[!!(immvalue_float(a) > immvalue_float(b))];
+ return (lt) ? m_imm_float[!!(immvalue_float(a) < immvalue_float(b))]
+ : m_imm_float[!!(immvalue_float(a) > immvalue_float(b))];
}
return nullptr;
}
float la = immvalue_float(a);
float lb = immvalue_float(b);
check_inexact_float(a, b);
- return (ast_expression*)m_imm_float[!(ne ? la == lb : la != lb)];
- } if (isvector(a) && isvector(b)) {
+ return m_imm_float[ne ? la != lb : la == lb];
+ } else if (isvector(a) && isvector(b)) {
vec3_t la = immvalue_vector(a);
vec3_t lb = immvalue_vector(b);
- return (ast_expression*)m_imm_float[!(ne ? vec3_cmp(la, lb) : !vec3_cmp(la, lb))];
+ bool compare = vec3_cmp(la, lb);
+ return m_imm_float[ne ? !compare : compare];
+ } else if (isstring(a) && isstring(b)) {
+ bool compare = !strcmp(immvalue_string(a), immvalue_string(b));
+ return m_imm_float[ne ? !compare : compare];
}
}
return nullptr;
if (fold_can_1(a) && isstring(a))
return constgen_float(strlen(immvalue_string(a)), false);
if (isarray(a))
- return constgen_float(a->initlist.size(), false);
+ return constgen_float(a->m_initlist.size(), false);
return nullptr;
}
#undef fold_can_1
#undef fold_can_2
-#define isfloat(X) ((X)->vtype == TYPE_FLOAT)
-/*#define isstring(X) ((X)->vtype == TYPE_STRING)*/
-/*#define isvector(X) ((X)->vtype == TYPE_VECTOR)*/
-#define fold_can_1(X) ((X)->hasvalue && (X)->cvq == CV_CONST)
+#define isfloat(X) ((X)->m_vtype == TYPE_FLOAT)
+/*#define isstring(X) ((X)->m_vtype == TYPE_STRING)*/
+/*#define isvector(X) ((X)->m_vtype == TYPE_VECTOR)*/
+#define fold_can_1(X) ((X)->m_hasvalue && (X)->m_cvq == CV_CONST)
/*#define fold_can_2(X,Y) (fold_can_1(X) && fold_can_1(Y))*/
qcfloat_t fold::immvalue_float(ir_value *value) {
- return value->constval.vfloat;
+ return value->m_constval.vfloat;
}
vec3_t fold::immvalue_vector(ir_value *value) {
- return value->constval.vvec;
+ return value->m_constval.vvec;
}
ast_expression *fold::superfluous(ast_expression *left, ast_expression *right, int op) {
ast_expression *ret = superfluous(left, right, op);
if (ret)
return ret;
- return (ast_expression*)ast_binary_new(ctx, op, left, right);
+ return new ast_binary(ctx, op, left, right);
}
int fold::cond(ir_value *condval, ast_function *func, ast_ifthen *branch) {
if (isfloat(condval) && fold_can_1(condval) && OPTS_OPTIMIZATION(OPTIM_CONST_FOLD_DCE)) {
- ast_expression_codegen *cgen;
ir_block *elide;
ir_value *dummy;
- bool istrue = (immvalue_float(condval) != 0.0f && branch->on_true);
- bool isfalse = (immvalue_float(condval) == 0.0f && branch->on_false);
- ast_expression *path = (istrue) ? branch->on_true :
- (isfalse) ? branch->on_false : nullptr;
+ bool istrue = (immvalue_float(condval) != 0.0f && branch->m_on_true);
+ bool isfalse = (immvalue_float(condval) == 0.0f && branch->m_on_false);
+ ast_expression *path = (istrue) ? branch->m_on_true :
+ (isfalse) ? branch->m_on_false : nullptr;
if (!path) {
/*
* no path to take implies that the evaluation is if(0) and there
return true;
}
- if (!(elide = ir_function_create_block(ast_ctx(branch), func->ir_func, ast_function_label(func, ((istrue) ? "ontrue" : "onfalse")))))
+ if (!(elide = ir_function_create_block(branch->m_context, func->m_ir_func, func->makeLabel((istrue) ? "ontrue" : "onfalse"))))
return false;
- if (!(*(cgen = path->codegen))((ast_expression*)path, func, false, &dummy))
+ if (!path->codegen(func, false, &dummy))
return false;
- if (!ir_block_create_jump(func->curblock, ast_ctx(branch), elide))
+ if (!ir_block_create_jump(func->m_curblock, branch->m_context, elide))
return false;
/*
* now the branch has been eliminated and the correct block for the constant evaluation
* is expanded into the current block for the function.
*/
- func->curblock = elide;
+ func->m_curblock = elide;
++opts_optimizationcount[OPTIM_CONST_FOLD_DCE];
return true;
}