From db9c37d18bcced1c3b0f1421044155b1d88f0b25 Mon Sep 17 00:00:00 2001 From: Dale Weiler Date: Thu, 15 Jan 2015 20:27:17 -0500 Subject: [PATCH 1/1] Rewrite constant folder in C++ --- ast.cpp | 15 +- fold.cpp | 552 ++++++++++++++++++++++++++--------------------------- fold.h | 106 ++++++++++ intrin.cpp | 117 ++++++------ intrin.h | 7 +- parser.cpp | 156 +++++++-------- parser.h | 29 +-- 7 files changed, 536 insertions(+), 446 deletions(-) create mode 100644 fold.h diff --git a/ast.cpp b/ast.cpp index 366d2a9..4768e6e 100644 --- a/ast.cpp +++ b/ast.cpp @@ -5,7 +5,8 @@ #include "gmqcc.h" #include "ast.h" -#include "parser.h" +#include "fold.h" +//#include "parser.h" #define ast_instantiate(T, ctx, destroyfn) \ T* self = (T*)mem_a(sizeof(T)); \ @@ -2560,7 +2561,7 @@ bool ast_ifthen_codegen(ast_ifthen *self, ast_function *func, bool lvalue, ir_va ir_block *ontrue_endblock = nullptr; ir_block *onfalse_endblock = nullptr; ir_block *merge = nullptr; - int fold = 0; + int folded = 0; /* We don't output any value, thus also don't care about r/lvalue */ (void)out; @@ -2580,8 +2581,8 @@ bool ast_ifthen_codegen(ast_ifthen *self, ast_function *func, bool lvalue, ir_va cond = func->curblock; /* try constant folding away the condition */ - if ((fold = fold_cond_ifthen(condval, func, self)) != -1) - return fold; + if ((folded = fold::cond_ifthen(condval, func, self)) != -1) + return folded; if (self->on_true) { /* create on-true block */ @@ -2663,7 +2664,7 @@ bool ast_ternary_codegen(ast_ternary *self, ast_function *func, bool lvalue, ir_ ir_block *ontrue, *ontrue_out = nullptr; ir_block *onfalse, *onfalse_out = nullptr; ir_block *merge; - int fold = 0; + int folded = 0; /* Ternary can never create an lvalue... */ if (lvalue) @@ -2689,8 +2690,8 @@ bool ast_ternary_codegen(ast_ternary *self, ast_function *func, bool lvalue, ir_ cond_out = func->curblock; /* try constant folding away the condition */ - if ((fold = fold_cond_ternary(condval, func, self)) != -1) - return fold; + if ((folded = fold::cond_ternary(condval, func, self)) != -1) + return folded; /* create on-true block */ ontrue = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "tern_T")); diff --git a/fold.cpp b/fold.cpp index a4bc878..aee8e24 100644 --- a/fold.cpp +++ b/fold.cpp @@ -1,7 +1,10 @@ #include #include +#include "fold.h" #include "ast.h" +#include "ir.h" + #include "parser.h" #define FOLD_STRING_UNTRANSLATE_HTSIZE 1024 @@ -27,7 +30,7 @@ typedef uint32_t sfloat_t; union sfloat_cast_t { qcfloat_t f; - sfloat_t s; + sfloat_t s; }; /* Exception flags */ @@ -854,15 +857,27 @@ end: return out; } -static lex_ctx_t fold_ctx(fold_t *fold) { +qcfloat_t fold::immvalue_float(ast_value *value) { + return value->constval.vfloat; +} + +vec3_t fold::immvalue_vector(ast_value *value) { + return value->constval.vvec; +} + +const char *fold::immvalue_string(ast_value *value) { + return value->constval.vstring; +} + +lex_ctx_t fold::ctx() { lex_ctx_t ctx; - if (fold->parser->lex) - return parser_ctx(fold->parser); + if (m_parser->lex) + return parser_ctx(m_parser); memset(&ctx, 0, sizeof(ctx)); return ctx; } -static GMQCC_INLINE bool fold_immediate_true(fold_t *fold, ast_value *v) { +bool fold::immediate_true(ast_value *v) { switch (v->expression.vtype) { case TYPE_FLOAT: return !!v->constval.vfloat; @@ -879,7 +894,7 @@ static GMQCC_INLINE bool fold_immediate_true(fold_t *fold, ast_value *v) { return true; return !!v->constval.vstring[0]; default: - compile_error(fold_ctx(fold), "internal error: fold_immediate_true on invalid type"); + compile_error(ctx(), "internal error: fold_immediate_true on invalid type"); break; } return !!v->constval.vfunc; @@ -892,39 +907,34 @@ static GMQCC_INLINE bool fold_immediate_true(fold_t *fold, ast_value *v) { #define fold_can_2(X, Y) (fold_can_1(X) && fold_can_1(Y)) -#define fold_immvalue_float(E) ((E)->constval.vfloat) -#define fold_immvalue_vector(E) ((E)->constval.vvec) -#define fold_immvalue_string(E) ((E)->constval.vstring) - -fold_t *fold_init(parser_t *parser) { - fold_t *fold = new fold_t; - fold->parser = parser; - fold->imm_string_untranslate = util_htnew(FOLD_STRING_UNTRANSLATE_HTSIZE); - fold->imm_string_dotranslate = util_htnew(FOLD_STRING_DOTRANSLATE_HTSIZE); +fold::fold() + : m_parser(nullptr) +{ +} - /* - * prime the tables with common constant values at constant - * locations. - */ - (void)fold_constgen_float(fold, 0.0f, false); - (void)fold_constgen_float(fold, 1.0f, false); - (void)fold_constgen_float(fold, -1.0f, false); - (void)fold_constgen_float(fold, 2.0f, false); +fold::fold(parser_t *parser) + : m_parser(parser) +{ + m_imm_string_untranslate = util_htnew(FOLD_STRING_UNTRANSLATE_HTSIZE); + m_imm_string_dotranslate = util_htnew(FOLD_STRING_DOTRANSLATE_HTSIZE); - (void)fold_constgen_vector(fold, vec3_create(0.0f, 0.0f, 0.0f)); - (void)fold_constgen_vector(fold, vec3_create(-1.0f, -1.0f, -1.0f)); + constgen_float(0.0f, false); + constgen_float(1.0f, false); + constgen_float(-1.0f, false); + constgen_float(2.0f, false); - return fold; + constgen_vector(vec3_create(0.0f, 0.0f, 0.0f)); + constgen_vector(vec3_create(-1.0f, -1.0f, -1.0f)); } -bool fold_generate(fold_t *fold, ir_builder *ir) { +bool fold::generate(ir_builder *ir) { // generate globals for immediate folded values ast_value *cur; - for (auto &it : fold->imm_float) + for (auto &it : m_imm_float) if (!ast_global_codegen((cur = it), ir, false)) goto err; - for (auto &it : fold->imm_vector) + for (auto &it : m_imm_vector) if (!ast_global_codegen((cur = it), ir, false)) goto err; - for (auto &it : fold->imm_string) + for (auto &it : m_imm_string) if (!ast_global_codegen((cur = it), ir, false)) goto err; return true; err: @@ -933,50 +943,51 @@ err: return false; } -void fold_cleanup(fold_t *fold) { - for (auto &it : fold->imm_float) ast_delete(it); - for (auto &it : fold->imm_vector) ast_delete(it); - for (auto &it : fold->imm_string) ast_delete(it); - - util_htdel(fold->imm_string_untranslate); - util_htdel(fold->imm_string_dotranslate); +fold::~fold() { +// TODO: parser lifetime so this is called when it should be +#if 0 + for (auto &it : m_imm_float) ast_delete(it); + for (auto &it : m_imm_vector) ast_delete(it); + for (auto &it : m_imm_string) ast_delete(it); - delete fold; + util_htdel(m_imm_string_untranslate); + util_htdel(m_imm_string_dotranslate); +#endif } -ast_expression *fold_constgen_float(fold_t *fold, qcfloat_t value, bool inexact) { - for (auto &it : fold->imm_float) +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; - ast_value *out = ast_value_new(fold_ctx(fold), "#IMMEDIATE", TYPE_FLOAT); + ast_value *out = ast_value_new(ctx(), "#IMMEDIATE", TYPE_FLOAT); out->cvq = CV_CONST; out->hasvalue = true; out->inexact = inexact; out->constval.vfloat = value; - fold->imm_float.push_back(out); + m_imm_float.push_back(out); return (ast_expression*)out; } -ast_expression *fold_constgen_vector(fold_t *fold, vec3_t value) { - for (auto &it : fold->imm_vector) +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; - ast_value *out = ast_value_new(fold_ctx(fold), "#IMMEDIATE", TYPE_VECTOR); + ast_value *out = ast_value_new(ctx(), "#IMMEDIATE", TYPE_VECTOR); out->cvq = CV_CONST; out->hasvalue = true; out->constval.vvec = value; - fold->imm_vector.push_back(out); + m_imm_vector.push_back(out); return (ast_expression*)out; } -ast_expression *fold_constgen_string(fold_t *fold, const char *str, bool translate) { - hash_table_t *table = (translate) ? fold->imm_string_untranslate : fold->imm_string_dotranslate; +ast_expression *fold::constgen_string(const char *str, bool translate) { + hash_table_t *table = translate ? m_imm_string_untranslate : m_imm_string_dotranslate; ast_value *out = nullptr; size_t hash = util_hthash(table, str); @@ -985,11 +996,11 @@ ast_expression *fold_constgen_string(fold_t *fold, const char *str, bool transla if (translate) { char name[32]; - util_snprintf(name, sizeof(name), "dotranslate_%lu", (unsigned long)(fold->parser->translated++)); - out = ast_value_new(parser_ctx(fold->parser), name, TYPE_STRING); + 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 */ } else { - out = ast_value_new(fold_ctx(fold), "#IMMEDIATE", TYPE_STRING); + out = ast_value_new(ctx(), "#IMMEDIATE", TYPE_STRING); } out->cvq = CV_CONST; @@ -997,23 +1008,19 @@ ast_expression *fold_constgen_string(fold_t *fold, const char *str, bool transla out->isimm = true; out->constval.vstring = parser_strdup(str); - fold->imm_string.push_back(out); + m_imm_string.push_back(out); util_htseth(table, str, hash, out); return (ast_expression*)out; } typedef union { - void (*callback)(void); + void (*callback)(void); sfloat_t (*binary)(sfloat_state_t *, sfloat_t, sfloat_t); sfloat_t (*unary)(sfloat_state_t *, sfloat_t); } float_check_callback_t; -static bool fold_check_except_float_impl(void (*callback)(void), - fold_t *fold, - ast_value *a, - ast_value *b) -{ +bool fold::check_except_float_impl(void (*callback)(void), ast_value *a, ast_value *b) { float_check_callback_t call; sfloat_state_t s; sfloat_cast_t ca; @@ -1023,10 +1030,10 @@ static bool fold_check_except_float_impl(void (*callback)(void), call.callback = callback; sfloat_init(&s); - ca.f = fold_immvalue_float(a); + ca.f = immvalue_float(a); if (b) { sfloat_cast_t cb; - cb.f = fold_immvalue_float(b); + cb.f = immvalue_float(b); call.binary(&s, ca.s, cb.s); } else { call.unary(&s, ca.s); @@ -1038,164 +1045,163 @@ static bool fold_check_except_float_impl(void (*callback)(void), if (!OPTS_FLAG(ARITHMETIC_EXCEPTIONS)) goto inexact_possible; - sfloat_check(fold_ctx(fold), &s, nullptr); + sfloat_check(ctx(), &s, nullptr); inexact_possible: return s.exceptionflags & SFLOAT_INEXACT; } -#define fold_check_except_float(CALLBACK, FOLD, A, B) \ - fold_check_except_float_impl(((void (*)(void))(CALLBACK)), (FOLD), (A), (B)) +#define check_except_float(CALLBACK, A, B) \ + check_except_float_impl(((void (*)(void))(CALLBACK)), (A), (B)) -static bool fold_check_inexact_float(fold_t *fold, ast_value *a, ast_value *b) { - lex_ctx_t ctx = fold_ctx(fold); +bool fold::check_inexact_float(ast_value *a, ast_value *b) { if (!OPTS_WARN(WARN_INEXACT_COMPARES)) return false; if (!a->inexact && !b->inexact) return false; - return compile_warning(ctx, WARN_INEXACT_COMPARES, "inexact value in comparison"); + return compile_warning(ctx(), WARN_INEXACT_COMPARES, "inexact value in comparison"); } -static GMQCC_INLINE ast_expression *fold_op_mul_vec(fold_t *fold, vec3_t vec, ast_value *sel, const char *set) { +ast_expression *fold::op_mul_vec(vec3_t vec, ast_value *sel, const char *set) { qcfloat_t x = (&vec.x)[set[0]-'x']; qcfloat_t y = (&vec.x)[set[1]-'x']; qcfloat_t z = (&vec.x)[set[2]-'x']; if (!y && !z) { ast_expression *out; ++opts_optimizationcount[OPTIM_VECTOR_COMPONENTS]; - out = (ast_expression*)ast_member_new(fold_ctx(fold), (ast_expression*)sel, set[0]-'x', nullptr); - out->node.keep = false; + out = (ast_expression*)ast_member_new(ctx(), (ast_expression*)sel, set[0]-'x', nullptr); + out->node.keep = false; ((ast_member*)out)->rvalue = true; if (x != -1.0f) - return (ast_expression*)ast_binary_new(fold_ctx(fold), INSTR_MUL_F, fold_constgen_float(fold, x, false), out); + return (ast_expression*)ast_binary_new(ctx(), INSTR_MUL_F, constgen_float(x, false), out); } return nullptr; } -static GMQCC_INLINE ast_expression *fold_op_neg(fold_t *fold, ast_value *a) { +ast_expression *fold::op_neg(ast_value *a) { if (isfloat(a)) { if (fold_can_1(a)) { /* Negation can produce inexact as well */ - bool inexact = fold_check_except_float(&sfloat_neg, fold, a, nullptr); - return fold_constgen_float(fold, -fold_immvalue_float(a), inexact); + bool inexact = check_except_float(&sfloat_neg, a, nullptr); + return constgen_float(-immvalue_float(a), inexact); } } else if (isvector(a)) { if (fold_can_1(a)) - return fold_constgen_vector(fold, vec3_neg(fold_ctx(fold), fold_immvalue_vector(a))); + return constgen_vector(vec3_neg(ctx(), immvalue_vector(a))); } return nullptr; } -static GMQCC_INLINE ast_expression *fold_op_not(fold_t *fold, ast_value *a) { +ast_expression *fold::op_not(ast_value *a) { if (isfloat(a)) { if (fold_can_1(a)) - return fold_constgen_float(fold, !fold_immvalue_float(a), false); + return constgen_float(!immvalue_float(a), false); } else if (isvector(a)) { if (fold_can_1(a)) - return fold_constgen_float(fold, vec3_notf(fold_immvalue_vector(a)), false); + return constgen_float(vec3_notf(immvalue_vector(a)), false); } else if (isstring(a)) { if (fold_can_1(a)) { if (OPTS_FLAG(TRUE_EMPTY_STRINGS)) - return fold_constgen_float(fold, !fold_immvalue_string(a), false); + return constgen_float(!immvalue_string(a), false); else - return fold_constgen_float(fold, !fold_immvalue_string(a) || !*fold_immvalue_string(a), false); + return constgen_float(!immvalue_string(a) || !*immvalue_string(a), false); } } return nullptr; } -static GMQCC_INLINE ast_expression *fold_op_add(fold_t *fold, ast_value *a, ast_value *b) { +ast_expression *fold::op_add(ast_value *a, ast_value *b) { if (isfloat(a)) { if (fold_can_2(a, b)) { - bool inexact = fold_check_except_float(&sfloat_add, fold, a, b); - return fold_constgen_float(fold, fold_immvalue_float(a) + fold_immvalue_float(b), inexact); + bool inexact = check_except_float(&sfloat_add, a, b); + return constgen_float(immvalue_float(a) + immvalue_float(b), inexact); } } else if (isvector(a)) { if (fold_can_2(a, b)) - return fold_constgen_vector(fold, vec3_add(fold_ctx(fold), - fold_immvalue_vector(a), - fold_immvalue_vector(b))); + return constgen_vector(vec3_add(ctx(), + immvalue_vector(a), + immvalue_vector(b))); } return nullptr; } -static GMQCC_INLINE ast_expression *fold_op_sub(fold_t *fold, ast_value *a, ast_value *b) { +ast_expression *fold::op_sub(ast_value *a, ast_value *b) { if (isfloat(a)) { if (fold_can_2(a, b)) { - bool inexact = fold_check_except_float(&sfloat_sub, fold, a, b); - return fold_constgen_float(fold, fold_immvalue_float(a) - fold_immvalue_float(b), inexact); + bool inexact = check_except_float(&sfloat_sub, a, b); + return constgen_float(immvalue_float(a) - immvalue_float(b), inexact); } } else if (isvector(a)) { if (fold_can_2(a, b)) - return fold_constgen_vector(fold, vec3_sub(fold_ctx(fold), - fold_immvalue_vector(a), - fold_immvalue_vector(b))); + return constgen_vector(vec3_sub(ctx(), + immvalue_vector(a), + immvalue_vector(b))); } return nullptr; } -static GMQCC_INLINE ast_expression *fold_op_mul(fold_t *fold, ast_value *a, ast_value *b) { +ast_expression *fold::op_mul(ast_value *a, ast_value *b) { if (isfloat(a)) { if (isvector(b)) { if (fold_can_2(a, b)) - return fold_constgen_vector(fold, vec3_mulvf(fold_ctx(fold), fold_immvalue_vector(b), fold_immvalue_float(a))); + return constgen_vector(vec3_mulvf(ctx(), immvalue_vector(b), immvalue_float(a))); } else { if (fold_can_2(a, b)) { - bool inexact = fold_check_except_float(&sfloat_mul, fold, a, b); - return fold_constgen_float(fold, fold_immvalue_float(a) * fold_immvalue_float(b), inexact); + bool inexact = check_except_float(&sfloat_mul, a, b); + return constgen_float(immvalue_float(a) * immvalue_float(b), inexact); } } } else if (isvector(a)) { if (isfloat(b)) { if (fold_can_2(a, b)) - return fold_constgen_vector(fold, vec3_mulvf(fold_ctx(fold), fold_immvalue_vector(a), fold_immvalue_float(b))); + return constgen_vector(vec3_mulvf(ctx(), immvalue_vector(a), immvalue_float(b))); } else { if (fold_can_2(a, b)) { - return fold_constgen_float(fold, vec3_mulvv(fold_ctx(fold), fold_immvalue_vector(a), fold_immvalue_vector(b)), false); + return constgen_float(vec3_mulvv(ctx(), immvalue_vector(a), immvalue_vector(b)), false); } else if (OPTS_OPTIMIZATION(OPTIM_VECTOR_COMPONENTS) && fold_can_1(a)) { ast_expression *out; - if ((out = fold_op_mul_vec(fold, fold_immvalue_vector(a), b, "xyz"))) return out; - if ((out = fold_op_mul_vec(fold, fold_immvalue_vector(a), b, "yxz"))) return out; - if ((out = fold_op_mul_vec(fold, fold_immvalue_vector(a), b, "zxy"))) return out; + if ((out = op_mul_vec(immvalue_vector(a), b, "xyz"))) return out; + if ((out = op_mul_vec(immvalue_vector(a), b, "yxz"))) return out; + if ((out = op_mul_vec(immvalue_vector(a), b, "zxy"))) return out; } else if (OPTS_OPTIMIZATION(OPTIM_VECTOR_COMPONENTS) && fold_can_1(b)) { ast_expression *out; - if ((out = fold_op_mul_vec(fold, fold_immvalue_vector(b), a, "xyz"))) return out; - if ((out = fold_op_mul_vec(fold, fold_immvalue_vector(b), a, "yxz"))) return out; - if ((out = fold_op_mul_vec(fold, fold_immvalue_vector(b), a, "zxy"))) return out; + if ((out = op_mul_vec(immvalue_vector(b), a, "xyz"))) return out; + if ((out = op_mul_vec(immvalue_vector(b), a, "yxz"))) return out; + if ((out = op_mul_vec(immvalue_vector(b), a, "zxy"))) return out; } } } return nullptr; } -static GMQCC_INLINE ast_expression *fold_op_div(fold_t *fold, ast_value *a, ast_value *b) { +ast_expression *fold::op_div(ast_value *a, ast_value *b) { if (isfloat(a)) { if (fold_can_2(a, b)) { - bool inexact = fold_check_except_float(&sfloat_div, fold, a, b); - return fold_constgen_float(fold, fold_immvalue_float(a) / fold_immvalue_float(b), inexact); + 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( - fold_ctx(fold), + ctx(), INSTR_MUL_F, (ast_expression*)a, - fold_constgen_float(fold, 1.0f / fold_immvalue_float(b), false) + constgen_float(1.0f / immvalue_float(b), false) ); } } else if (isvector(a)) { if (fold_can_2(a, b)) { - return fold_constgen_vector(fold, vec3_mulvf(fold_ctx(fold), fold_immvalue_vector(a), 1.0f / fold_immvalue_float(b))); + return constgen_vector(vec3_mulvf(ctx(), immvalue_vector(a), 1.0f / immvalue_float(b))); } else { return (ast_expression*)ast_binary_new( - fold_ctx(fold), + ctx(), INSTR_MUL_VF, (ast_expression*)a, (fold_can_1(b)) - ? (ast_expression*)fold_constgen_float(fold, 1.0f / fold_immvalue_float(b), false) + ? (ast_expression*)constgen_float(1.0f / immvalue_float(b), false) : (ast_expression*)ast_binary_new( - fold_ctx(fold), + ctx(), INSTR_DIV_F, - (ast_expression*)fold->imm_float[1], + (ast_expression*)m_imm_float[1], (ast_expression*)b ) ); @@ -1204,83 +1210,82 @@ static GMQCC_INLINE ast_expression *fold_op_div(fold_t *fold, ast_value *a, ast_ return nullptr; } -static GMQCC_INLINE ast_expression *fold_op_mod(fold_t *fold, ast_value *a, ast_value *b) { +ast_expression *fold::op_mod(ast_value *a, ast_value *b) { return (fold_can_2(a, b)) - ? fold_constgen_float(fold, fmod(fold_immvalue_float(a), fold_immvalue_float(b)), false) + ? constgen_float(fmod(immvalue_float(a), immvalue_float(b)), false) : nullptr; } -static GMQCC_INLINE ast_expression *fold_op_bor(fold_t *fold, ast_value *a, ast_value *b) { +ast_expression *fold::op_bor(ast_value *a, ast_value *b) { if (isfloat(a)) { if (fold_can_2(a, b)) - return fold_constgen_float(fold, (qcfloat_t)(((qcint_t)fold_immvalue_float(a)) | ((qcint_t)fold_immvalue_float(b))), false); + return constgen_float((qcfloat_t)(((qcint_t)immvalue_float(a)) | ((qcint_t)immvalue_float(b))), false); } else { if (isvector(b)) { if (fold_can_2(a, b)) - return fold_constgen_vector(fold, vec3_or(fold_immvalue_vector(a), fold_immvalue_vector(b))); + return constgen_vector(vec3_or(immvalue_vector(a), immvalue_vector(b))); } else { if (fold_can_2(a, b)) - return fold_constgen_vector(fold, vec3_orvf(fold_immvalue_vector(a), fold_immvalue_float(b))); + return constgen_vector(vec3_orvf(immvalue_vector(a), immvalue_float(b))); } } return nullptr; } -static GMQCC_INLINE ast_expression *fold_op_band(fold_t *fold, ast_value *a, ast_value *b) { +ast_expression *fold::op_band(ast_value *a, ast_value *b) { if (isfloat(a)) { if (fold_can_2(a, b)) - return fold_constgen_float(fold, (qcfloat_t)(((qcint_t)fold_immvalue_float(a)) & ((qcint_t)fold_immvalue_float(b))), false); + return constgen_float((qcfloat_t)(((qcint_t)immvalue_float(a)) & ((qcint_t)immvalue_float(b))), false); } else { if (isvector(b)) { if (fold_can_2(a, b)) - return fold_constgen_vector(fold, vec3_and(fold_immvalue_vector(a), fold_immvalue_vector(b))); + return constgen_vector(vec3_and(immvalue_vector(a), immvalue_vector(b))); } else { if (fold_can_2(a, b)) - return fold_constgen_vector(fold, vec3_andvf(fold_immvalue_vector(a), fold_immvalue_float(b))); + return constgen_vector(vec3_andvf(immvalue_vector(a), immvalue_float(b))); } } return nullptr; } -static GMQCC_INLINE ast_expression *fold_op_xor(fold_t *fold, ast_value *a, ast_value *b) { +ast_expression *fold::op_xor(ast_value *a, ast_value *b) { if (isfloat(a)) { if (fold_can_2(a, b)) - return fold_constgen_float(fold, (qcfloat_t)(((qcint_t)fold_immvalue_float(a)) ^ ((qcint_t)fold_immvalue_float(b))), false); + return constgen_float((qcfloat_t)(((qcint_t)immvalue_float(a)) ^ ((qcint_t)immvalue_float(b))), false); } else { if (fold_can_2(a, b)) { if (isvector(b)) - return fold_constgen_vector(fold, vec3_xor(fold_immvalue_vector(a), fold_immvalue_vector(b))); + return constgen_vector(vec3_xor(immvalue_vector(a), immvalue_vector(b))); else - return fold_constgen_vector(fold, vec3_xorvf(fold_immvalue_vector(a), fold_immvalue_float(b))); + return constgen_vector(vec3_xorvf(immvalue_vector(a), immvalue_float(b))); } } return nullptr; } -static GMQCC_INLINE ast_expression *fold_op_lshift(fold_t *fold, ast_value *a, ast_value *b) { +ast_expression *fold::op_lshift(ast_value *a, ast_value *b) { if (fold_can_2(a, b) && isfloats(a, b)) - return fold_constgen_float(fold, (qcfloat_t)floorf(fold_immvalue_float(a) * powf(2.0f, fold_immvalue_float(b))), false); + return constgen_float((qcfloat_t)floorf(immvalue_float(a) * powf(2.0f, immvalue_float(b))), false); return nullptr; } -static GMQCC_INLINE ast_expression *fold_op_rshift(fold_t *fold, ast_value *a, ast_value *b) { +ast_expression *fold::op_rshift(ast_value *a, ast_value *b) { if (fold_can_2(a, b) && isfloats(a, b)) - return fold_constgen_float(fold, (qcfloat_t)floorf(fold_immvalue_float(a) / powf(2.0f, fold_immvalue_float(b))), false); + return constgen_float((qcfloat_t)floorf(immvalue_float(a) / powf(2.0f, immvalue_float(b))), false); return nullptr; } -static GMQCC_INLINE ast_expression *fold_op_andor(fold_t *fold, ast_value *a, ast_value *b, float expr) { +ast_expression *fold::op_andor(ast_value *a, ast_value *b, float expr) { if (fold_can_2(a, b)) { if (OPTS_FLAG(PERL_LOGIC)) { if (expr) - return (fold_immediate_true(fold, a)) ? (ast_expression*)a : (ast_expression*)b; + return immediate_true(a) ? (ast_expression*)a : (ast_expression*)b; else - return (fold_immediate_true(fold, a)) ? (ast_expression*)b : (ast_expression*)a; + return immediate_true(a) ? (ast_expression*)b : (ast_expression*)a; } else { - return fold_constgen_float ( - fold, - ((expr) ? (fold_immediate_true(fold, a) || fold_immediate_true(fold, b)) - : (fold_immediate_true(fold, a) && fold_immediate_true(fold, b))) + return constgen_float( + ((expr) ? (immediate_true(a) || immediate_true(b)) + : (immediate_true(a) && immediate_true(b))) ? 1 : 0, false @@ -1290,89 +1295,89 @@ static GMQCC_INLINE ast_expression *fold_op_andor(fold_t *fold, ast_value *a, as return nullptr; } -static GMQCC_INLINE ast_expression *fold_op_tern(fold_t *fold, ast_value *a, ast_value *b, ast_value *c) { +ast_expression *fold::op_tern(ast_value *a, ast_value *b, ast_value *c) { if (fold_can_1(a)) { - return fold_immediate_true(fold, a) + return immediate_true(a) ? (ast_expression*)b : (ast_expression*)c; } return nullptr; } -static GMQCC_INLINE ast_expression *fold_op_exp(fold_t *fold, ast_value *a, ast_value *b) { +ast_expression *fold::op_exp(ast_value *a, ast_value *b) { if (fold_can_2(a, b)) - return fold_constgen_float(fold, (qcfloat_t)powf(fold_immvalue_float(a), fold_immvalue_float(b)), false); + return constgen_float((qcfloat_t)powf(immvalue_float(a), immvalue_float(b)), false); return nullptr; } -static GMQCC_INLINE ast_expression *fold_op_lteqgt(fold_t *fold, ast_value *a, ast_value *b) { +ast_expression *fold::op_lteqgt(ast_value *a, ast_value *b) { if (fold_can_2(a,b)) { - fold_check_inexact_float(fold, a, b); - if (fold_immvalue_float(a) < fold_immvalue_float(b)) return (ast_expression*)fold->imm_float[2]; - if (fold_immvalue_float(a) == fold_immvalue_float(b)) return (ast_expression*)fold->imm_float[0]; - if (fold_immvalue_float(a) > fold_immvalue_float(b)) return (ast_expression*)fold->imm_float[1]; + 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]; } return nullptr; } -static GMQCC_INLINE ast_expression *fold_op_ltgt(fold_t *fold, ast_value *a, ast_value *b, bool lt) { +ast_expression *fold::op_ltgt(ast_value *a, ast_value *b, bool lt) { if (fold_can_2(a, b)) { - fold_check_inexact_float(fold, a, b); - return (lt) ? (ast_expression*)fold->imm_float[!!(fold_immvalue_float(a) < fold_immvalue_float(b))] - : (ast_expression*)fold->imm_float[!!(fold_immvalue_float(a) > fold_immvalue_float(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 nullptr; } -static GMQCC_INLINE ast_expression *fold_op_cmp(fold_t *fold, ast_value *a, ast_value *b, bool ne) { +ast_expression *fold::op_cmp(ast_value *a, ast_value *b, bool ne) { if (fold_can_2(a, b)) { if (isfloat(a) && isfloat(b)) { - float la = fold_immvalue_float(a); - float lb = fold_immvalue_float(b); - fold_check_inexact_float(fold, a, b); - return (ast_expression*)fold->imm_float[!(ne ? la == lb : la != lb)]; + 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)) { - vec3_t la = fold_immvalue_vector(a); - vec3_t lb = fold_immvalue_vector(b); - return (ast_expression*)fold->imm_float[!(ne ? vec3_cmp(la, lb) : !vec3_cmp(la, lb))]; + 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))]; } } return nullptr; } -static GMQCC_INLINE ast_expression *fold_op_bnot(fold_t *fold, ast_value *a) { +ast_expression *fold::op_bnot(ast_value *a) { if (isfloat(a)) { if (fold_can_1(a)) - return fold_constgen_float(fold, -1-fold_immvalue_float(a), false); + return constgen_float(-1-immvalue_float(a), false); } else { if (isvector(a)) { if (fold_can_1(a)) - return fold_constgen_vector(fold, vec3_not(fold_immvalue_vector(a))); + return constgen_vector(vec3_not(immvalue_vector(a))); } } return nullptr; } -static GMQCC_INLINE ast_expression *fold_op_cross(fold_t *fold, ast_value *a, ast_value *b) { +ast_expression *fold::op_cross(ast_value *a, ast_value *b) { if (fold_can_2(a, b)) - return fold_constgen_vector(fold, vec3_cross(fold_ctx(fold), - fold_immvalue_vector(a), - fold_immvalue_vector(b))); + return constgen_vector(vec3_cross(ctx(), + immvalue_vector(a), + immvalue_vector(b))); return nullptr; } -static GMQCC_INLINE ast_expression *fold_op_length(fold_t *fold, ast_value *a) { +ast_expression *fold::op_length(ast_value *a) { if (fold_can_1(a) && isstring(a)) - return fold_constgen_float(fold, strlen(fold_immvalue_string(a)), false); + return constgen_float(strlen(immvalue_string(a)), false); if (isarray(a)) - return fold_constgen_float(fold, a->initlist.size(), false); + return constgen_float(a->initlist.size(), false); return nullptr; } -ast_expression *fold_op(fold_t *fold, const oper_info *info, ast_expression **opexprs) { - ast_value *a = (ast_value*)opexprs[0]; - ast_value *b = (ast_value*)opexprs[1]; - ast_value *c = (ast_value*)opexprs[2]; +ast_expression *fold::op(const oper_info *info, ast_expression **opexprs) { + ast_value *a = (ast_value*)opexprs[0]; + ast_value *b = (ast_value*)opexprs[1]; + ast_value *c = (ast_value*)opexprs[2]; ast_expression *e = nullptr; /* can a fold operation be applied to this operator usage? */ @@ -1384,55 +1389,46 @@ ast_expression *fold_op(fold_t *fold, const oper_info *info, ast_expression **op case 2: if(!b) return nullptr; case 1: if(!a) { - compile_error(fold_ctx(fold), "internal error: fold_op no operands to fold\n"); + compile_error(ctx(), "internal error: fold_op no operands to fold\n"); return nullptr; } } - /* - * we could use a boolean and default case but ironically gcc produces - * invalid broken assembly from that operation. clang/tcc get it right, - * but interestingly ignore compiling this to a jump-table when I do that, - * this happens to be the most efficent method, since you have per-level - * granularity on the pointer check happening only for the case you check - * it in. Opposed to the default method which would involve a boolean and - * pointer check after wards. - */ #define fold_op_case(ARGS, ARGS_OPID, OP, ARGS_FOLD) \ case opid##ARGS ARGS_OPID: \ - if ((e = fold_op_##OP ARGS_FOLD)) { \ + if ((e = op_##OP ARGS_FOLD)) { \ ++opts_optimizationcount[OPTIM_CONST_FOLD]; \ } \ return e switch(info->id) { - fold_op_case(2, ('-', 'P'), neg, (fold, a)); - fold_op_case(2, ('!', 'P'), not, (fold, a)); - fold_op_case(1, ('+'), add, (fold, a, b)); - fold_op_case(1, ('-'), sub, (fold, a, b)); - fold_op_case(1, ('*'), mul, (fold, a, b)); - fold_op_case(1, ('/'), div, (fold, a, b)); - fold_op_case(1, ('%'), mod, (fold, a, b)); - fold_op_case(1, ('|'), bor, (fold, a, b)); - fold_op_case(1, ('&'), band, (fold, a, b)); - fold_op_case(1, ('^'), xor, (fold, a, b)); - fold_op_case(1, ('<'), ltgt, (fold, a, b, true)); - fold_op_case(1, ('>'), ltgt, (fold, a, b, false)); - fold_op_case(2, ('<', '<'), lshift, (fold, a, b)); - fold_op_case(2, ('>', '>'), rshift, (fold, a, b)); - fold_op_case(2, ('|', '|'), andor, (fold, a, b, true)); - fold_op_case(2, ('&', '&'), andor, (fold, a, b, false)); - fold_op_case(2, ('?', ':'), tern, (fold, a, b, c)); - fold_op_case(2, ('*', '*'), exp, (fold, a, b)); - fold_op_case(3, ('<','=','>'), lteqgt, (fold, a, b)); - fold_op_case(2, ('!', '='), cmp, (fold, a, b, true)); - fold_op_case(2, ('=', '='), cmp, (fold, a, b, false)); - fold_op_case(2, ('~', 'P'), bnot, (fold, a)); - fold_op_case(2, ('>', '<'), cross, (fold, a, b)); - fold_op_case(3, ('l', 'e', 'n'), length, (fold, a)); + fold_op_case(2, ('-', 'P'), neg, (a)); + fold_op_case(2, ('!', 'P'), not, (a)); + fold_op_case(1, ('+'), add, (a, b)); + fold_op_case(1, ('-'), sub, (a, b)); + fold_op_case(1, ('*'), mul, (a, b)); + fold_op_case(1, ('/'), div, (a, b)); + fold_op_case(1, ('%'), mod, (a, b)); + fold_op_case(1, ('|'), bor, (a, b)); + fold_op_case(1, ('&'), band, (a, b)); + fold_op_case(1, ('^'), xor, (a, b)); + fold_op_case(1, ('<'), ltgt, (a, b, true)); + fold_op_case(1, ('>'), ltgt, (a, b, false)); + fold_op_case(2, ('<', '<'), lshift, (a, b)); + fold_op_case(2, ('>', '>'), rshift, (a, b)); + fold_op_case(2, ('|', '|'), andor, (a, b, true)); + fold_op_case(2, ('&', '&'), andor, (a, b, false)); + fold_op_case(2, ('?', ':'), tern, (a, b, c)); + fold_op_case(2, ('*', '*'), exp, (a, b)); + fold_op_case(3, ('<','=','>'), lteqgt, (a, b)); + fold_op_case(2, ('!', '='), cmp, (a, b, true)); + fold_op_case(2, ('=', '='), cmp, (a, b, false)); + fold_op_case(2, ('~', 'P'), bnot, (a)); + fold_op_case(2, ('>', '<'), cross, (a, b)); + fold_op_case(3, ('l', 'e', 'n'), length, (a)); } #undef fold_op_case - compile_error(fold_ctx(fold), "internal error: attempted to constant-fold for unsupported operator"); + compile_error(ctx(), "internal error: attempted to constant-fold for unsupported operator"); return nullptr; } @@ -1441,69 +1437,68 @@ ast_expression *fold_op(fold_t *fold, const oper_info *info, ast_expression **op * folding, primarily: individual functions for each intrinsics to fold, * and a generic selection function. */ -static GMQCC_INLINE ast_expression *fold_intrin_isfinite(fold_t *fold, ast_value *a) { - return fold_constgen_float(fold, isfinite(fold_immvalue_float(a)), false); +ast_expression *fold::intrinsic_isfinite(ast_value *a) { + return constgen_float(isfinite(immvalue_float(a)), false); } -static GMQCC_INLINE ast_expression *fold_intrin_isinf(fold_t *fold, ast_value *a) { - return fold_constgen_float(fold, isinf(fold_immvalue_float(a)), false); +ast_expression *fold::intrinsic_isinf(ast_value *a) { + return constgen_float(isinf(immvalue_float(a)), false); } -static GMQCC_INLINE ast_expression *fold_intrin_isnan(fold_t *fold, ast_value *a) { - return fold_constgen_float(fold, isnan(fold_immvalue_float(a)), false); +ast_expression *fold::intrinsic_isnan(ast_value *a) { + return constgen_float(isnan(immvalue_float(a)), false); } -static GMQCC_INLINE ast_expression *fold_intrin_isnormal(fold_t *fold, ast_value *a) { - return fold_constgen_float(fold, isnormal(fold_immvalue_float(a)), false); +ast_expression *fold::intrinsic_isnormal(ast_value *a) { + return constgen_float(isnormal(immvalue_float(a)), false); } -static GMQCC_INLINE ast_expression *fold_intrin_signbit(fold_t *fold, ast_value *a) { - return fold_constgen_float(fold, signbit(fold_immvalue_float(a)), false); +ast_expression *fold::intrinsic_signbit(ast_value *a) { + return constgen_float(signbit(immvalue_float(a)), false); } -static GMQCC_INLINE ast_expression *fold_intirn_acosh(fold_t *fold, ast_value *a) { - return fold_constgen_float(fold, acoshf(fold_immvalue_float(a)), false); +ast_expression *fold::intrinsic_acosh(ast_value *a) { + return constgen_float(acoshf(immvalue_float(a)), false); } -static GMQCC_INLINE ast_expression *fold_intrin_asinh(fold_t *fold, ast_value *a) { - return fold_constgen_float(fold, asinhf(fold_immvalue_float(a)), false); +ast_expression *fold::intrinsic_asinh(ast_value *a) { + return constgen_float(asinhf(immvalue_float(a)), false); } -static GMQCC_INLINE ast_expression *fold_intrin_atanh(fold_t *fold, ast_value *a) { - return fold_constgen_float(fold, (float)atanh(fold_immvalue_float(a)), false); +ast_expression *fold::intrinsic_atanh(ast_value *a) { + return constgen_float((float)atanh(immvalue_float(a)), false); } -static GMQCC_INLINE ast_expression *fold_intrin_exp(fold_t *fold, ast_value *a) { - return fold_constgen_float(fold, expf(fold_immvalue_float(a)), false); +ast_expression *fold::intrinsic_exp(ast_value *a) { + return constgen_float(expf(immvalue_float(a)), false); } -static GMQCC_INLINE ast_expression *fold_intrin_exp2(fold_t *fold, ast_value *a) { - return fold_constgen_float(fold, exp2f(fold_immvalue_float(a)), false); +ast_expression *fold::intrinsic_exp2(ast_value *a) { + return constgen_float(exp2f(immvalue_float(a)), false); } -static GMQCC_INLINE ast_expression *fold_intrin_expm1(fold_t *fold, ast_value *a) { - return fold_constgen_float(fold, expm1f(fold_immvalue_float(a)), false); +ast_expression *fold::intrinsic_expm1(ast_value *a) { + return constgen_float(expm1f(immvalue_float(a)), false); } -static GMQCC_INLINE ast_expression *fold_intrin_mod(fold_t *fold, ast_value *lhs, ast_value *rhs) { - return fold_constgen_float(fold, fmodf(fold_immvalue_float(lhs), fold_immvalue_float(rhs)), false); +ast_expression *fold::intrinsic_mod(ast_value *lhs, ast_value *rhs) { + return constgen_float(fmodf(immvalue_float(lhs), immvalue_float(rhs)), false); } -static GMQCC_INLINE ast_expression *fold_intrin_pow(fold_t *fold, ast_value *lhs, ast_value *rhs) { - return fold_constgen_float(fold, powf(fold_immvalue_float(lhs), fold_immvalue_float(rhs)), false); +ast_expression *fold::intrinsic_pow(ast_value *lhs, ast_value *rhs) { + return constgen_float(powf(immvalue_float(lhs), immvalue_float(rhs)), false); } -static GMQCC_INLINE ast_expression *fold_intrin_fabs(fold_t *fold, ast_value *a) { - return fold_constgen_float(fold, fabsf(fold_immvalue_float(a)), false); +ast_expression *fold::intrinsic_fabs(ast_value *a) { + return constgen_float(fabsf(immvalue_float(a)), false); } - -ast_expression *fold_intrin(fold_t *fold, const char *intrin, ast_expression **arg) { +ast_expression *fold::intrinsic(const char *intrinsic, ast_expression **arg) { ast_expression *ret = nullptr; - ast_value *a = (ast_value*)arg[0]; - ast_value *b = (ast_value*)arg[1]; - - if (!strcmp(intrin, "isfinite")) ret = fold_intrin_isfinite(fold, a); - if (!strcmp(intrin, "isinf")) ret = fold_intrin_isinf(fold, a); - if (!strcmp(intrin, "isnan")) ret = fold_intrin_isnan(fold, a); - if (!strcmp(intrin, "isnormal")) ret = fold_intrin_isnormal(fold, a); - if (!strcmp(intrin, "signbit")) ret = fold_intrin_signbit(fold, a); - if (!strcmp(intrin, "acosh")) ret = fold_intirn_acosh(fold, a); - if (!strcmp(intrin, "asinh")) ret = fold_intrin_asinh(fold, a); - if (!strcmp(intrin, "atanh")) ret = fold_intrin_atanh(fold, a); - if (!strcmp(intrin, "exp")) ret = fold_intrin_exp(fold, a); - if (!strcmp(intrin, "exp2")) ret = fold_intrin_exp2(fold, a); - if (!strcmp(intrin, "expm1")) ret = fold_intrin_expm1(fold, a); - if (!strcmp(intrin, "mod")) ret = fold_intrin_mod(fold, a, b); - if (!strcmp(intrin, "pow")) ret = fold_intrin_pow(fold, a, b); - if (!strcmp(intrin, "fabs")) ret = fold_intrin_fabs(fold, a); + ast_value *a = (ast_value*)arg[0]; + ast_value *b = (ast_value*)arg[1]; + + if (!strcmp(intrinsic, "isfinite")) ret = intrinsic_isfinite(a); + if (!strcmp(intrinsic, "isinf")) ret = intrinsic_isinf(a); + if (!strcmp(intrinsic, "isnan")) ret = intrinsic_isnan(a); + if (!strcmp(intrinsic, "isnormal")) ret = intrinsic_isnormal(a); + if (!strcmp(intrinsic, "signbit")) ret = intrinsic_signbit(a); + if (!strcmp(intrinsic, "acosh")) ret = intrinsic_acosh(a); + if (!strcmp(intrinsic, "asinh")) ret = intrinsic_asinh(a); + if (!strcmp(intrinsic, "atanh")) ret = intrinsic_atanh(a); + if (!strcmp(intrinsic, "exp")) ret = intrinsic_exp(a); + if (!strcmp(intrinsic, "exp2")) ret = intrinsic_exp2(a); + if (!strcmp(intrinsic, "expm1")) ret = intrinsic_expm1(a); + if (!strcmp(intrinsic, "mod")) ret = intrinsic_mod(a, b); + if (!strcmp(intrinsic, "pow")) ret = intrinsic_pow(a, b); + if (!strcmp(intrinsic, "fabs")) ret = intrinsic_fabs(a); if (ret) ++opts_optimizationcount[OPTIM_CONST_FOLD]; @@ -1521,22 +1516,27 @@ ast_expression *fold_intrin(fold_t *fold, const char *intrin, ast_expression **a #undef isfloat #undef isstring #undef isvector -#undef fold_immvalue_float -#undef fold_immvalue_string -#undef fold_immvalue_vector +#undef fold__immvalue_float +#undef fold__immvalue_string +#undef fold__immvalue_vector #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_immvalue_float(X) ((X)->constval.vfloat) -#define fold_immvalue_vector(X) ((X)->constval.vvec) -/*#define fold_immvalue_string(X) ((X)->constval.vstring)*/ #define fold_can_1(X) ((X)->hasvalue && (X)->cvq == CV_CONST) /*#define fold_can_2(X,Y) (fold_can_1(X) && fold_can_1(Y))*/ -static ast_expression *fold_superfluous(ast_expression *left, ast_expression *right, int op) { +qcfloat_t fold::immvalue_float(ir_value *value) { + return value->constval.vfloat; +} + +vec3_t fold::immvalue_vector(ir_value *value) { + return value->constval.vvec; +} + +ast_expression *fold::superfluous(ast_expression *left, ast_expression *right, int op) { ast_expression *swapped = nullptr; /* using this as bool */ ast_value *load; @@ -1554,7 +1554,7 @@ static ast_expression *fold_superfluous(ast_expression *left, ast_expression *ri if (swapped) return nullptr; case INSTR_MUL_F: - if (fold_immvalue_float(load) == 1.0f) { + if (immvalue_float(load) == 1.0f) { ++opts_optimizationcount[OPTIM_PEEPHOLE]; ast_unref(right); return left; @@ -1566,7 +1566,7 @@ static ast_expression *fold_superfluous(ast_expression *left, ast_expression *ri if (swapped) return nullptr; case INSTR_ADD_F: - if (fold_immvalue_float(load) == 0.0f) { + if (immvalue_float(load) == 0.0f) { ++opts_optimizationcount[OPTIM_PEEPHOLE]; ast_unref(right); return left; @@ -1574,7 +1574,7 @@ static ast_expression *fold_superfluous(ast_expression *left, ast_expression *ri break; case INSTR_MUL_V: - if (vec3_cmp(fold_immvalue_vector(load), vec3_create(1, 1, 1))) { + if (vec3_cmp(immvalue_vector(load), vec3_create(1, 1, 1))) { ++opts_optimizationcount[OPTIM_PEEPHOLE]; ast_unref(right); return left; @@ -1585,7 +1585,7 @@ static ast_expression *fold_superfluous(ast_expression *left, ast_expression *ri if (swapped) return nullptr; case INSTR_ADD_V: - if (vec3_cmp(fold_immvalue_vector(load), vec3_create(0, 0, 0))) { + if (vec3_cmp(immvalue_vector(load), vec3_create(0, 0, 0))) { ++opts_optimizationcount[OPTIM_PEEPHOLE]; ast_unref(right); return left; @@ -1596,20 +1596,20 @@ static ast_expression *fold_superfluous(ast_expression *left, ast_expression *ri return nullptr; } -ast_expression *fold_binary(lex_ctx_t ctx, int op, ast_expression *left, ast_expression *right) { - ast_expression *ret = fold_superfluous(left, right, op); +ast_expression *fold::binary(lex_ctx_t ctx, int op, ast_expression *left, ast_expression *right) { + ast_expression *ret = superfluous(left, right, op); if (ret) return ret; return (ast_expression*)ast_binary_new(ctx, op, left, right); } -static GMQCC_INLINE int fold_cond(ir_value *condval, ast_function *func, ast_ifthen *branch) { +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 = (fold_immvalue_float(condval) != 0.0f && branch->on_true); - bool isfalse = (fold_immvalue_float(condval) == 0.0f && branch->on_false); + 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; if (!path) { @@ -1638,10 +1638,10 @@ static GMQCC_INLINE int fold_cond(ir_value *condval, ast_function *func, ast_ift return -1; /* nothing done */ } -int fold_cond_ternary(ir_value *condval, ast_function *func, ast_ternary *branch) { - return fold_cond(condval, func, (ast_ifthen*)branch); +int fold::cond_ternary(ir_value *condval, ast_function *func, ast_ternary *branch) { + return cond(condval, func, (ast_ifthen*)branch); } -int fold_cond_ifthen(ir_value *condval, ast_function *func, ast_ifthen *branch) { - return fold_cond(condval, func, branch); +int fold::cond_ifthen(ir_value *condval, ast_function *func, ast_ifthen *branch) { + return cond(condval, func, branch); } diff --git a/fold.h b/fold.h new file mode 100644 index 0000000..b29d422 --- /dev/null +++ b/fold.h @@ -0,0 +1,106 @@ +#ifndef GMQCC_FOLD_HDR +#define GMQCC_FOLD_HDR +#include "lexer.h" +#include "gmqcc.h" + +struct ir_builder; +struct ir_value; + +struct ast_function; +struct ast_ifthen; +struct ast_ternary; +struct ast_expression; +struct ast_value; + +struct parser_t; + +struct fold { + fold(); + fold(parser_t *parser); + ~fold(); + + bool generate(ir_builder *ir); + ast_expression *op(const oper_info *info, ast_expression **opexprs); + ast_expression *intrinsic(const char *intrinsic, ast_expression **arg); + + static int cond_ternary(ir_value *condval, ast_function *func, ast_ternary *branch); + static int cond_ifthen(ir_value *condval, ast_function *func, ast_ifthen *branch); + + static ast_expression *superfluous(ast_expression *left, ast_expression *right, int op); + static ast_expression *binary(lex_ctx_t ctx, int op, ast_expression *left, ast_expression *right); + + ast_expression *constgen_float(qcfloat_t value, bool inexact); + ast_expression *constgen_vector(vec3_t value); + ast_expression *constgen_string(const char *str, bool translate); + + ast_value *imm_float(size_t index) const { return m_imm_float[index]; } + ast_value *imm_vector(size_t index) const { return m_imm_vector[index]; } + +protected: + static qcfloat_t immvalue_float(ast_value *value); + static vec3_t immvalue_vector(ast_value *value); + static const char *immvalue_string(ast_value *value); + + lex_ctx_t ctx(); + + bool immediate_true(ast_value *v); + + bool check_except_float_impl(void (*callback)(void), ast_value *a, ast_value *b); + bool check_inexact_float(ast_value *a, ast_value *b); + + ast_expression *op_mul_vec(vec3_t vec, ast_value *sel, const char *set); + ast_expression *op_neg(ast_value *a); + ast_expression *op_not(ast_value *a); + ast_expression *op_add(ast_value *a, ast_value *b); + ast_expression *op_sub(ast_value *a, ast_value *b); + ast_expression *op_mul(ast_value *a, ast_value *b); + ast_expression *op_div(ast_value *a, ast_value *b); + ast_expression *op_mod(ast_value *a, ast_value *b); + ast_expression *op_bor(ast_value *a, ast_value *b); + ast_expression *op_band(ast_value *a, ast_value *b); + ast_expression *op_xor(ast_value *a, ast_value *b); + ast_expression *op_lshift(ast_value *a, ast_value *b); + ast_expression *op_rshift(ast_value *a, ast_value *b); + ast_expression *op_andor(ast_value *a, ast_value *b, float expr); + ast_expression *op_tern(ast_value *a, ast_value *b, ast_value *c); + ast_expression *op_exp(ast_value *a, ast_value *b); + ast_expression *op_lteqgt(ast_value *a, ast_value *b); + ast_expression *op_ltgt(ast_value *a, ast_value *b, bool lt); + ast_expression *op_cmp(ast_value *a, ast_value *b, bool ne); + ast_expression *op_bnot(ast_value *a); + ast_expression *op_cross(ast_value *a, ast_value *b); + ast_expression *op_length(ast_value *a); + + ast_expression *intrinsic_isfinite(ast_value *a); + ast_expression *intrinsic_isinf(ast_value *a); + ast_expression *intrinsic_isnan(ast_value *a); + ast_expression *intrinsic_isnormal(ast_value *a); + ast_expression *intrinsic_signbit(ast_value *a); + ast_expression *intrinsic_acosh(ast_value *a); + ast_expression *intrinsic_asinh(ast_value *a); + ast_expression *intrinsic_atanh(ast_value *a); + ast_expression *intrinsic_exp(ast_value *a); + ast_expression *intrinsic_exp2(ast_value *a); + ast_expression *intrinsic_expm1(ast_value *a); + ast_expression *intrinsic_mod(ast_value *lhs, ast_value *rhs); + ast_expression *intrinsic_pow(ast_value *lhs, ast_value *rhs); + ast_expression *intrinsic_fabs(ast_value *a); + + static qcfloat_t immvalue_float(ir_value *value); + static vec3_t immvalue_vector(ir_value *value); + + static int cond(ir_value *condval, ast_function *func, ast_ifthen *branch); + +private: + friend struct intrin; + + std::vector m_imm_float; + std::vector m_imm_vector; + std::vector m_imm_string; + hash_table_t *m_imm_string_untranslate; /* map */ + hash_table_t *m_imm_string_dotranslate; /* map */ + parser_t *m_parser; + bool m_initialized; +}; + +#endif diff --git a/intrin.cpp b/intrin.cpp index 2916367..e55cf0f 100644 --- a/intrin.cpp +++ b/intrin.cpp @@ -1,4 +1,7 @@ #include + +#include "ast.h" +#include "fold.h" #include "parser.h" lex_ctx_t intrin::ctx() const { @@ -104,7 +107,7 @@ ast_expression *intrin::isinf_() { ctx(), INSTR_NE_F, (ast_expression*)x, - (ast_expression*)m_fold->imm_float[0] + (ast_expression*)m_fold->m_imm_float[0] ), (ast_expression*)ast_binary_new( ctx(), @@ -225,10 +228,10 @@ ast_expression *intrin::signbit_() { ctx(), INSTR_LT, (ast_expression*)x, - (ast_expression*)m_fold->imm_float[0] + (ast_expression*)m_fold->m_imm_float[0] ), - (ast_expression*)m_fold->imm_float[1], - (ast_expression*)m_fold->imm_float[0] + (ast_expression*)m_fold->m_imm_float[1], + (ast_expression*)m_fold->m_imm_float[0] ) ) ); @@ -264,7 +267,7 @@ ast_expression *intrin::acosh_() { (ast_expression*)x, (ast_expression*)x ), - (ast_expression*)m_fold->imm_float[1] + (ast_expression*)m_fold->m_imm_float[1] ) ); @@ -317,7 +320,7 @@ ast_expression *intrin::asinh_() { (ast_expression*)x, (ast_expression*)x ), - (ast_expression*)m_fold->imm_float[1] + (ast_expression*)m_fold->m_imm_float[1] ) ); @@ -366,13 +369,13 @@ ast_expression *intrin::atanh_() { (ast_expression*)ast_binary_new( ctx(), INSTR_ADD_F, - (ast_expression*)m_fold->imm_float[1], + (ast_expression*)m_fold->m_imm_float[1], (ast_expression*)x ), (ast_expression*)ast_binary_new( ctx(), INSTR_SUB_F, - (ast_expression*)m_fold->imm_float[1], + (ast_expression*)m_fold->m_imm_float[1], (ast_expression*)x ) ) @@ -383,7 +386,7 @@ ast_expression *intrin::atanh_() { (ast_expression*)ast_binary_new( ctx(), INSTR_MUL_F, - (ast_expression*)fold_constgen_float(m_fold, 0.5, false), + (ast_expression*)m_fold->constgen_float(0.5, false), (ast_expression*)calllog ) ); @@ -425,7 +428,7 @@ ast_expression *intrin::exp_() { ctx(), INSTR_STORE_F, (ast_expression*)sum, - (ast_expression*)m_fold->imm_float[1] + (ast_expression*)m_fold->m_imm_float[1] ) ); @@ -435,7 +438,7 @@ ast_expression *intrin::exp_() { ctx(), INSTR_STORE_F, (ast_expression*)acc, - (ast_expression*)m_fold->imm_float[1] + (ast_expression*)m_fold->m_imm_float[1] ) ); @@ -451,14 +454,14 @@ ast_expression *intrin::exp_() { ctx(), INSTR_STORE_F, (ast_expression*)i, - (ast_expression*)m_fold->imm_float[1] + (ast_expression*)m_fold->m_imm_float[1] ), /* i < 200; */ (ast_expression*)ast_binary_new( ctx(), INSTR_LT, (ast_expression*)i, - (ast_expression*)fold_constgen_float(m_fold, 200.0f, false) + (ast_expression*)m_fold->constgen_float(200.0f, false) ), false, nullptr, @@ -469,7 +472,7 @@ ast_expression *intrin::exp_() { INSTR_STORE_F, INSTR_ADD_F, (ast_expression*)i, - (ast_expression*)m_fold->imm_float[1] + (ast_expression*)m_fold->m_imm_float[1] ), /* sum += (acc *= (x / i)) */ (ast_expression*)ast_binstore_new( @@ -520,7 +523,7 @@ ast_expression *intrin::exp2_() { val->expression.params.push_back(arg1); - callpow->params.push_back((ast_expression*)m_fold->imm_float[3]); + callpow->params.push_back((ast_expression*)m_fold->m_imm_float[3]); callpow->params.push_back((ast_expression*)arg1); /* return */ @@ -561,7 +564,7 @@ ast_expression *intrin::expm1_() { ctx(), INSTR_SUB_F, (ast_expression*)callexp, - (ast_expression*)m_fold->imm_float[1] + (ast_expression*)m_fold->m_imm_float[1] ) ) ); @@ -670,11 +673,11 @@ ast_expression *intrin::pow_() { ctx(), INSTR_EQ_F, (ast_expression*)exp, - (ast_expression*)m_fold->imm_float[0] + (ast_expression*)m_fold->m_imm_float[0] ), (ast_expression*)ast_return_new( ctx(), - (ast_expression*)m_fold->imm_float[1] + (ast_expression*)m_fold->m_imm_float[1] ), nullptr ) @@ -691,7 +694,7 @@ ast_expression *intrin::pow_() { ctx(), INSTR_EQ_F, (ast_expression*)exp, - (ast_expression*)m_fold->imm_float[1] + (ast_expression*)m_fold->m_imm_float[1] ), (ast_expression*)ast_return_new( ctx(), @@ -722,14 +725,14 @@ ast_expression *intrin::pow_() { ctx(), INSTR_LT, (ast_expression*)exp, - (ast_expression*)m_fold->imm_float[0] + (ast_expression*)m_fold->m_imm_float[0] ), (ast_expression*)ast_return_new( ctx(), (ast_expression*)ast_binary_new( ctx(), INSTR_DIV_F, - (ast_expression*)m_fold->imm_float[1], + (ast_expression*)m_fold->m_imm_float[1], (ast_expression*)callpow1 ) ), @@ -744,7 +747,7 @@ ast_expression *intrin::pow_() { ctx(), INSTR_DIV_F, (ast_expression*)exp, - (ast_expression*)m_fold->imm_float[3] /* 2.0f */ + (ast_expression*)m_fold->m_imm_float[3] /* 2.0f */ ) ); @@ -786,7 +789,7 @@ ast_expression *intrin::pow_() { ctx(), INSTR_GE, (ast_expression*)exp, - (ast_expression*)m_fold->imm_float[1] + (ast_expression*)m_fold->m_imm_float[1] ), (ast_expression*)expgt1, nullptr @@ -809,7 +812,7 @@ ast_expression *intrin::pow_() { (ast_expression*)ast_store_new(ctx(), INSTR_STORE_F, (ast_expression*)low, - (ast_expression*)m_fold->imm_float[0] + (ast_expression*)m_fold->m_imm_float[0] ) ); body->exprs.push_back( @@ -817,7 +820,7 @@ ast_expression *intrin::pow_() { ctx(), INSTR_STORE_F, (ast_expression*)high, - (ast_expression*)m_fold->imm_float[1] + (ast_expression*)m_fold->m_imm_float[1] ) ); @@ -847,7 +850,7 @@ ast_expression *intrin::pow_() { ctx(), INSTR_DIV_F, (ast_expression*)high, - (ast_expression*)m_fold->imm_float[3] /* 2.0f */ + (ast_expression*)m_fold->m_imm_float[3] /* 2.0f */ ) ) ); @@ -899,7 +902,7 @@ ast_expression *intrin::pow_() { (ast_expression*)ast_binary_new( ctx(), INSTR_DIV_F, - (ast_expression*)m_fold->imm_float[1], + (ast_expression*)m_fold->m_imm_float[1], (ast_expression*)square ) ) @@ -956,7 +959,7 @@ ast_expression *intrin::pow_() { (ast_expression*)low, (ast_expression*)high ), - (ast_expression*)m_fold->imm_float[3] /* 2.0f */ + (ast_expression*)m_fold->m_imm_float[3] /* 2.0f */ ) ) ); @@ -987,7 +990,7 @@ ast_expression *intrin::pow_() { ctx(), INSTR_GT, (ast_expression*)callfabs, - (ast_expression*)fold_constgen_float(m_fold, QC_POW_EPSILON, false) + (ast_expression*)m_fold->constgen_float(QC_POW_EPSILON, false) ), /* pre not */ false, @@ -1066,10 +1069,10 @@ ast_expression *intrin::mod_() { ctx(), INSTR_LT, (ast_expression*)div, - (ast_expression*)m_fold->imm_float[0] + (ast_expression*)m_fold->m_imm_float[0] ), - (ast_expression*)m_fold->imm_float[2], - (ast_expression*)m_fold->imm_float[1] + (ast_expression*)m_fold->m_imm_float[2], + (ast_expression*)m_fold->m_imm_float[1] ) ) ); @@ -1132,7 +1135,7 @@ ast_expression *intrin::fabs_() { ctx(), INSTR_LE, (ast_expression*)arg1, - (ast_expression*)m_fold->imm_float[0] + (ast_expression*)m_fold->m_imm_float[0] ), (ast_expression*)ast_unary_new( ctx(), @@ -1172,7 +1175,7 @@ ast_expression *intrin::epsilon_() { ctx(), INSTR_STORE_F, (ast_expression*)eps, - (ast_expression*)m_fold->imm_float[0] + (ast_expression*)m_fold->m_imm_float[0] ) ); @@ -1188,15 +1191,15 @@ ast_expression *intrin::epsilon_() { (ast_expression*)ast_binary_new( ctx(), INSTR_ADD_F, - (ast_expression*)m_fold->imm_float[1], + (ast_expression*)m_fold->m_imm_float[1], (ast_expression*)ast_binary_new( ctx(), INSTR_MUL_F, (ast_expression*)eps, - (ast_expression*)m_fold->imm_float[3] /* 2.0f */ + (ast_expression*)m_fold->m_imm_float[3] /* 2.0f */ ) ), - (ast_expression*)m_fold->imm_float[1] + (ast_expression*)m_fold->m_imm_float[1] ), false, nullptr, @@ -1205,7 +1208,7 @@ ast_expression *intrin::epsilon_() { INSTR_STORE_F, INSTR_DIV_F, (ast_expression*)eps, - (ast_expression*)m_fold->imm_float[3] /* 2.0f */ + (ast_expression*)m_fold->m_imm_float[3] /* 2.0f */ ) ) ); @@ -1242,7 +1245,7 @@ ast_expression *intrin::nan_() { ctx(), INSTR_STORE_F, (ast_expression*)x, - (ast_expression*)m_fold->imm_float[0] + (ast_expression*)m_fold->m_imm_float[0] ) ); @@ -1288,7 +1291,7 @@ ast_expression *intrin::inf_() { ctx(), INSTR_STORE_F, (ast_expression*)((i == 0) ? x : y), - (ast_expression*)m_fold->imm_float[i] + (ast_expression*)m_fold->m_imm_float[i] ) ); } @@ -1421,7 +1424,7 @@ ast_expression *intrin::ln_() { ctx(), INSTR_STORE_F, (ast_expression*)sign, - (ast_expression*)m_fold->imm_float[1] + (ast_expression*)m_fold->m_imm_float[1] ) ); @@ -1453,7 +1456,7 @@ ast_expression *intrin::ln_() { INSTR_STORE_F, (ast_expression*)((j) ? ((i) ? B_iminus1 : A_i) : ((i) ? A_iminus1 : B_i)), - (ast_expression*)m_fold->imm_float[j] + (ast_expression*)m_fold->m_imm_float[j] ) ); } @@ -1478,7 +1481,7 @@ ast_expression *intrin::ln_() { (ast_expression*)ast_binary_new( ctx(), INSTR_DIV_F, - (ast_expression*)m_fold->imm_float[1], + (ast_expression*)m_fold->m_imm_float[1], (ast_expression*)((i) ? base : power) ) ) @@ -1489,7 +1492,7 @@ ast_expression *intrin::ln_() { INSTR_STORE_F, INSTR_MUL_F, (ast_expression*)sign, - (ast_expression*)m_fold->imm_float[2] + (ast_expression*)m_fold->m_imm_float[2] ) ); } @@ -1514,13 +1517,13 @@ ast_expression *intrin::ln_() { ctx(), INSTR_LE, (ast_expression*)power, - (ast_expression*)m_fold->imm_float[0] + (ast_expression*)m_fold->m_imm_float[0] ), (ast_expression*)ast_binary_new( ctx(), INSTR_LE, (ast_expression*)base, - (ast_expression*)m_fold->imm_float[0] + (ast_expression*)m_fold->m_imm_float[0] ) ), (ast_expression*)ast_return_new( @@ -1542,7 +1545,7 @@ ast_expression *intrin::ln_() { ctx(), INSTR_LT, (ast_expression*)((i) ? base : power), - (ast_expression*)m_fold->imm_float[1] + (ast_expression*)m_fold->m_imm_float[1] ), (ast_expression*)((i) ? blt1 : plt1), nullptr @@ -1569,7 +1572,7 @@ ast_expression *intrin::ln_() { ctx(), INSTR_STORE_F, (ast_expression*)nth, - (ast_expression*)m_fold->imm_float[0] + (ast_expression*)m_fold->m_imm_float[0] ) ); @@ -1589,7 +1592,7 @@ ast_expression *intrin::ln_() { ctx(), INSTR_STORE_F, (ast_expression*)n2, - (ast_expression*)m_fold->imm_float[1] + (ast_expression*)m_fold->m_imm_float[1] ) ); @@ -1630,7 +1633,7 @@ ast_expression *intrin::ln_() { INSTR_STORE_F, INSTR_MUL_F, (ast_expression*)n2, - (ast_expression*)m_fold->imm_float[3] /* 2.0f */ + (ast_expression*)m_fold->m_imm_float[3] /* 2.0f */ ) ); @@ -1788,7 +1791,7 @@ ast_expression *intrin::ln_() { (ast_expression*)ast_binary_new( ctx(), INSTR_ADD_F, - (ast_expression*)m_fold->imm_float[1], + (ast_expression*)m_fold->m_imm_float[1], (ast_expression*)eps ) ), @@ -1822,7 +1825,7 @@ ast_expression *intrin::ln_() { ctx(), nullptr, /* for(; 1; ) ?? (can this be nullptr too?) */ - (ast_expression*)m_fold->imm_float[1], + (ast_expression*)m_fold->m_imm_float[1], false, nullptr, false, @@ -1864,7 +1867,7 @@ ast_expression *intrin::log_variant(const char *name, float base) { val->expression.params.push_back(arg1); callln->params.push_back((ast_expression*)arg1); - callln->params.push_back((ast_expression*)fold_constgen_float(m_fold, base, false)); + callln->params.push_back((ast_expression*)m_fold->constgen_float(base, false)); body->exprs.push_back( (ast_expression*)ast_return_new( @@ -1909,7 +1912,7 @@ ast_expression *intrin::shift_variant(const char *name, size_t instr) { val->expression.params.push_back(b); /* = pow(2, b) */ - callpow->params.push_back((ast_expression*)m_fold->imm_float[3]); + callpow->params.push_back((ast_expression*)m_fold->m_imm_float[3]); callpow->params.push_back((ast_expression*)b); /* = floor(a [instr] ) */ @@ -1957,7 +1960,7 @@ ast_expression *intrin::debug_typestring() { intrin::intrin(parser_t *parser) : m_parser(parser) - , m_fold(parser->fold) + , m_fold(&parser->m_fold) { static const intrin_func_t intrinsics[] = { {&intrin::isfinite_, "__builtin_isfinite", "isfinite", 1}, @@ -1994,7 +1997,7 @@ intrin::intrin(parser_t *parser) } } -ast_expression *intrin::fold(ast_value *val, ast_expression **exprs) { +ast_expression *intrin::do_fold(ast_value *val, ast_expression **exprs) { if (!val || !val->name) return nullptr; static constexpr size_t kPrefixLength = 10; // "__builtin_" @@ -2002,7 +2005,7 @@ ast_expression *intrin::fold(ast_value *val, ast_expression **exprs) { if (!strcmp(val->name, it.name)) return (vec_size(exprs) != it.args) ? nullptr - : fold_intrin(m_fold, val->name + kPrefixLength, exprs); + : m_fold->intrinsic(val->name + kPrefixLength, exprs); } return nullptr; } diff --git a/intrin.h b/intrin.h index d3d2df3..e0151d8 100644 --- a/intrin.h +++ b/intrin.h @@ -2,7 +2,7 @@ #define GMQCC_INTRIN_HDR #include "gmqcc.h" -struct fold_t; +struct fold; struct parser_t; struct ast_function; @@ -23,7 +23,7 @@ struct intrin { intrin(parser_t *parser); ast_expression *debug_typestring(); - ast_expression *fold(ast_value *val, ast_expression **exprs); + ast_expression *do_fold(ast_value *val, ast_expression **exprs); ast_expression *func_try(size_t offset, const char *compare); ast_expression *func_self(const char *name, const char *from); ast_expression *func(const char *name); @@ -65,10 +65,9 @@ protected: private: parser_t *m_parser; - fold_t *m_fold; + fold *m_fold; std::vector m_intrinsics; std::vector m_generated; - }; diff --git a/parser.cpp b/parser.cpp index eea0863..631adf6 100644 --- a/parser.cpp +++ b/parser.cpp @@ -1,6 +1,9 @@ #include #include +#include "intrin.h" +#include "fold.h" +#include "ast.h" #include "parser.h" #define PARSER_HT_LOCALS 2 @@ -430,7 +433,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) out = exprs[0]; break; case opid2('-','P'): - if ((out = fold_op(parser->fold, op, exprs))) + if ((out = parser->m_fold.op(op, exprs))) break; if (exprs[0]->vtype != TYPE_FLOAT && @@ -446,7 +449,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) break; case opid2('!','P'): - if (!(out = fold_op(parser->fold, op, exprs))) { + if (!(out = parser->m_fold.op(op, exprs))) { switch (exprs[0]->vtype) { case TYPE_FLOAT: out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_F, exprs[0]); @@ -484,13 +487,13 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) type_name[exprs[1]->vtype]); return false; } - if (!(out = fold_op(parser->fold, op, exprs))) { + if (!(out = parser->m_fold.op(op, exprs))) { switch (exprs[0]->vtype) { case TYPE_FLOAT: - out = fold_binary(ctx, INSTR_ADD_F, exprs[0], exprs[1]); + out = fold::binary(ctx, INSTR_ADD_F, exprs[0], exprs[1]); break; case TYPE_VECTOR: - out = fold_binary(ctx, INSTR_ADD_V, exprs[0], exprs[1]); + out = fold::binary(ctx, INSTR_ADD_V, exprs[0], exprs[1]); break; default: compile_error(ctx, "invalid types used in expression: cannot add type %s and %s", @@ -509,13 +512,13 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) type_name[exprs[0]->vtype]); return false; } - if (!(out = fold_op(parser->fold, op, exprs))) { + if (!(out = parser->m_fold.op(op, exprs))) { switch (exprs[0]->vtype) { case TYPE_FLOAT: - out = fold_binary(ctx, INSTR_SUB_F, exprs[0], exprs[1]); + out = fold::binary(ctx, INSTR_SUB_F, exprs[0], exprs[1]); break; case TYPE_VECTOR: - out = fold_binary(ctx, INSTR_SUB_V, exprs[0], exprs[1]); + out = fold::binary(ctx, INSTR_SUB_V, exprs[0], exprs[1]); break; default: compile_error(ctx, "invalid types used in expression: cannot subtract type %s from %s", @@ -538,19 +541,19 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) type_name[exprs[0]->vtype]); return false; } - if (!(out = fold_op(parser->fold, op, exprs))) { + if (!(out = parser->m_fold.op(op, exprs))) { switch (exprs[0]->vtype) { case TYPE_FLOAT: if (exprs[1]->vtype == TYPE_VECTOR) - out = fold_binary(ctx, INSTR_MUL_FV, exprs[0], exprs[1]); + out = fold::binary(ctx, INSTR_MUL_FV, exprs[0], exprs[1]); else - out = fold_binary(ctx, INSTR_MUL_F, exprs[0], exprs[1]); + out = fold::binary(ctx, INSTR_MUL_F, exprs[0], exprs[1]); break; case TYPE_VECTOR: if (exprs[1]->vtype == TYPE_FLOAT) - out = fold_binary(ctx, INSTR_MUL_VF, exprs[0], exprs[1]); + out = fold::binary(ctx, INSTR_MUL_VF, exprs[0], exprs[1]); else - out = fold_binary(ctx, INSTR_MUL_V, exprs[0], exprs[1]); + out = fold::binary(ctx, INSTR_MUL_V, exprs[0], exprs[1]); break; default: compile_error(ctx, "invalid types used in expression: cannot multiply types %s and %s", @@ -568,9 +571,9 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) compile_error(ctx, "invalid types used in expression: cannot divide types %s and %s", ty1, ty2); return false; } - if (!(out = fold_op(parser->fold, op, exprs))) { + if (!(out = parser->m_fold.op(op, exprs))) { if (exprs[0]->vtype == TYPE_FLOAT) - out = fold_binary(ctx, INSTR_DIV_F, exprs[0], exprs[1]); + out = fold::binary(ctx, INSTR_DIV_F, exprs[0], exprs[1]); else { ast_type_to_string(exprs[0], ty1, sizeof(ty1)); ast_type_to_string(exprs[1], ty2, sizeof(ty2)); @@ -586,7 +589,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) type_name[exprs[0]->vtype], type_name[exprs[1]->vtype]); return false; - } else if (!(out = fold_op(parser->fold, op, exprs))) { + } else if (!(out = parser->m_fold.op(op, exprs))) { /* generate a call to __builtin_mod */ ast_expression *mod = parser->m_intrin.func("mod"); ast_call *call = nullptr; @@ -617,13 +620,13 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) return false; } - if (!(out = fold_op(parser->fold, op, exprs))) { + if (!(out = parser->m_fold.op(op, exprs))) { /* * IF the first expression is float, the following will be too * since scalar ^ vector is not allowed. */ if (exprs[0]->vtype == TYPE_FLOAT) { - out = fold_binary(ctx, + out = fold::binary(ctx, (op->id == opid1('^') ? VINSTR_BITXOR : op->id == opid1('|') ? INSTR_BITOR : INSTR_BITAND), exprs[0], exprs[1]); } else { @@ -636,11 +639,11 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) * Bitop all the values of the vector components against the * vectors components in question. */ - out = fold_binary(ctx, + out = fold::binary(ctx, (op->id == opid1('^') ? VINSTR_BITXOR_V : op->id == opid1('|') ? VINSTR_BITOR_V : VINSTR_BITAND_V), exprs[0], exprs[1]); } else { - out = fold_binary(ctx, + out = fold::binary(ctx, (op->id == opid1('^') ? VINSTR_BITXOR_VF : op->id == opid1('|') ? VINSTR_BITOR_VF : VINSTR_BITAND_VF), exprs[0], exprs[1]); } @@ -657,9 +660,9 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) return false; } - if (!(out = fold_op(parser->fold, op, exprs))) { + if (!(out = parser->m_fold.op(op, exprs))) { ast_expression *shift = parser->m_intrin.func((op->id == opid2('<','<')) ? "__builtin_lshift" : "__builtin_rshift"); - ast_call *call = ast_call_new(parser_ctx(parser), shift); + ast_call *call = ast_call_new(parser_ctx(parser), shift); call->params.push_back(exprs[0]); call->params.push_back(exprs[1]); out = (ast_expression*)call; @@ -675,9 +678,9 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) return false; } - if(!(out = fold_op(parser->fold, op, exprs))) { + if(!(out = parser->m_fold.op(op, exprs))) { ast_expression *shift = parser->m_intrin.func((op->id == opid3('<','<','=')) ? "__builtin_lshift" : "__builtin_rshift"); - ast_call *call = ast_call_new(parser_ctx(parser), shift); + ast_call *call = ast_call_new(parser_ctx(parser), shift); call->params.push_back(exprs[0]); call->params.push_back(exprs[1]); out = (ast_expression*)ast_store_new( @@ -694,7 +697,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) generated_op += 1; /* INSTR_OR */ case opid2('&','&'): generated_op += INSTR_AND; - if (!(out = fold_op(parser->fold, op, exprs))) { + if (!(out = parser->m_fold.op(op, exprs))) { if (OPTS_FLAG(PERL_LOGIC) && !ast_compare_type(exprs[0], exprs[1])) { ast_type_to_string(exprs[0], ty1, sizeof(ty1)); ast_type_to_string(exprs[1], ty2, sizeof(ty2)); @@ -725,7 +728,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) } } } - out = fold_binary(ctx, generated_op, exprs[0], exprs[1]); + out = fold::binary(ctx, generated_op, exprs[0], exprs[1]); } break; @@ -741,7 +744,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) compile_error(ctx, "operands of ternary expression must have the same type, got %s and %s", ty1, ty2); return false; } - if (!(out = fold_op(parser->fold, op, exprs))) + if (!(out = parser->m_fold.op(op, exprs))) out = (ast_expression*)ast_ternary_new(ctx, exprs[0], exprs[1], exprs[2]); break; @@ -754,7 +757,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) return false; } - if (!(out = fold_op(parser->fold, op, exprs))) { + if (!(out = parser->m_fold.op(op, exprs))) { ast_call *gencall = ast_call_new(parser_ctx(parser), parser->m_intrin.func("pow")); gencall->params.push_back(exprs[0]); gencall->params.push_back(exprs[1]); @@ -771,12 +774,12 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) return false; } - if (!(out = fold_op(parser->fold, op, exprs))) { - out = fold_binary( - parser_ctx(parser), - VINSTR_CROSS, - exprs[0], - exprs[1] + if (!(out = parser->m_fold.op(op, exprs))) { + out = fold::binary( + parser_ctx(parser), + VINSTR_CROSS, + exprs[0], + exprs[1] ); } @@ -792,7 +795,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) return false; } - if (!(out = fold_op(parser->fold, op, exprs))) { + if (!(out = parser->m_fold.op(op, exprs))) { /* This whole block is NOT fold_binary safe */ ast_binary *eq = ast_binary_new(ctx, INSTR_EQ_F, exprs[0], exprs[1]); @@ -802,15 +805,15 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) out = (ast_expression*)ast_ternary_new(ctx, (ast_expression*)ast_binary_new(ctx, INSTR_LT, exprs[0], exprs[1]), /* out = -1 */ - (ast_expression*)parser->fold->imm_float[2], + (ast_expression*)parser->m_fold.imm_float(2), /* } else { */ /* if (eq) { */ (ast_expression*)ast_ternary_new(ctx, (ast_expression*)eq, /* out = 0 */ - (ast_expression*)parser->fold->imm_float[0], + (ast_expression*)parser->m_fold.imm_float(0), /* } else { */ /* out = 1 */ - (ast_expression*)parser->fold->imm_float[1] + (ast_expression*)parser->m_fold.imm_float(1) /* } */ ) /* } */ @@ -833,8 +836,8 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) type_name[exprs[1]->vtype]); return false; } - if (!(out = fold_op(parser->fold, op, exprs))) - out = fold_binary(ctx, generated_op, exprs[0], exprs[1]); + if (!(out = parser->m_fold.op(op, exprs))) + out = fold::binary(ctx, generated_op, exprs[0], exprs[1]); break; case opid2('!', '='): if (exprs[0]->vtype != exprs[1]->vtype) { @@ -843,8 +846,8 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) type_name[exprs[1]->vtype]); return false; } - if (!(out = fold_op(parser->fold, op, exprs))) - out = fold_binary(ctx, type_ne_instr[exprs[0]->vtype], exprs[0], exprs[1]); + if (!(out = parser->m_fold.op(op, exprs))) + out = fold::binary(ctx, type_ne_instr[exprs[0]->vtype], exprs[0], exprs[1]); break; case opid2('=', '='): if (exprs[0]->vtype != exprs[1]->vtype) { @@ -853,8 +856,8 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) type_name[exprs[1]->vtype]); return false; } - if (!(out = fold_op(parser->fold, op, exprs))) - out = fold_binary(ctx, type_eq_instr[exprs[0]->vtype], exprs[0], exprs[1]); + if (!(out = parser->m_fold.op(op, exprs))) + out = fold::binary(ctx, type_eq_instr[exprs[0]->vtype], exprs[0], exprs[1]); break; case opid1('='): @@ -937,11 +940,11 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) if (ast_istype(exprs[0], ast_entfield)) { out = (ast_expression*)ast_binstore_new(ctx, INSTR_STOREP_F, addop, exprs[0], - (ast_expression*)parser->fold->imm_float[1]); + (ast_expression*)parser->m_fold.imm_float(1)); } else { out = (ast_expression*)ast_binstore_new(ctx, INSTR_STORE_F, addop, exprs[0], - (ast_expression*)parser->fold->imm_float[1]); + (ast_expression*)parser->m_fold.imm_float(1)); } break; case opid3('S','+','+'): @@ -963,17 +966,17 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) if (ast_istype(exprs[0], ast_entfield)) { out = (ast_expression*)ast_binstore_new(ctx, INSTR_STOREP_F, addop, exprs[0], - (ast_expression*)parser->fold->imm_float[1]); + (ast_expression*)parser->m_fold.imm_float(1)); } else { out = (ast_expression*)ast_binstore_new(ctx, INSTR_STORE_F, addop, exprs[0], - (ast_expression*)parser->fold->imm_float[1]); + (ast_expression*)parser->m_fold.imm_float(1)); } if (!out) return false; - out = fold_binary(ctx, subop, + out = fold::binary(ctx, subop, out, - (ast_expression*)parser->fold->imm_float[1]); + (ast_expression*)parser->m_fold.imm_float(1)); break; case opid2('+','='): @@ -1038,8 +1041,8 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) out = (ast_expression*)ast_binstore_new(ctx, assignop, INSTR_MUL_VF, exprs[0], exprs[1]); } else { - out = fold_binary(ctx, INSTR_DIV_F, - (ast_expression*)parser->fold->imm_float[1], + out = fold::binary(ctx, INSTR_DIV_F, + (ast_expression*)parser->m_fold.imm_float(1), exprs[1]); if (!out) { compile_error(ctx, "internal error: failed to generate division"); @@ -1097,9 +1100,9 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) else assignop = type_store_instr[exprs[0]->vtype]; if (exprs[0]->vtype == TYPE_FLOAT) - out = fold_binary(ctx, INSTR_BITAND, exprs[0], exprs[1]); + out = fold::binary(ctx, INSTR_BITAND, exprs[0], exprs[1]); else - out = fold_binary(ctx, VINSTR_BITAND_V, exprs[0], exprs[1]); + out = fold::binary(ctx, VINSTR_BITAND_V, exprs[0], exprs[1]); if (!out) return false; (void)check_write_to(ctx, exprs[0]); @@ -1124,7 +1127,7 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) compile_error(ast_ctx(exprs[0]), "operand of length operator not a valid constant expression"); return false; } - out = fold_op(parser->fold, op, exprs); + out = parser->m_fold.op(op, exprs); break; case opid2('~', 'P'): @@ -1133,11 +1136,11 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy) compile_error(ast_ctx(exprs[0]), "invalid type for bit not: %s", ty1); return false; } - if (!(out = fold_op(parser->fold, op, exprs))) { + if (!(out = parser->m_fold.op(op, exprs))) { if (exprs[0]->vtype == TYPE_FLOAT) { - out = fold_binary(ctx, INSTR_SUB_F, (ast_expression*)parser->fold->imm_float[2], exprs[0]); + out = fold::binary(ctx, INSTR_SUB_F, (ast_expression*)parser->m_fold.imm_float(2), exprs[0]); } else { - out = fold_binary(ctx, INSTR_SUB_V, (ast_expression*)parser->fold->imm_vector[1], exprs[0]); + out = fold::binary(ctx, INSTR_SUB_V, (ast_expression*)parser->m_fold.imm_vector(1), exprs[0]); } } break; @@ -1198,7 +1201,7 @@ static bool parser_close_call(parser_t *parser, shunt *sy) ast_type_to_string(sy->out.back().out, ty, sizeof(ty)); ast_unref(sy->out.back().out); sy->out[fid] = syexp(ast_ctx(sy->out.back().out), - (ast_expression*)fold_constgen_string(parser->fold, ty, false)); + (ast_expression*)parser->m_fold.constgen_string(ty, false)); sy->out.pop_back(); return true; } @@ -1233,7 +1236,7 @@ static bool parser_close_call(parser_t *parser, shunt *sy) for (i = 0; i < paramcount; i++) vec_push(exprs, sy->out[fid+1 + i].out); - if (!(foldval = parser->m_intrin.fold((ast_value*)fun, exprs))) { + if (!(foldval = parser->m_intrin.do_fold((ast_value*)fun, exprs))) { vec_free(exprs); goto fold_leave; } @@ -1275,7 +1278,7 @@ static bool parser_close_call(parser_t *parser, shunt *sy) if ((fun->flags & AST_FLAG_VARIADIC) && !(/*funval->cvq == CV_CONST && */ funval->hasvalue && funval->constval.vfunc->builtin)) { - call->va_count = (ast_expression*)fold_constgen_float(parser->fold, (qcfloat_t)paramcount, false); + call->va_count = (ast_expression*)parser->m_fold.constgen_float((qcfloat_t)paramcount, false); } } @@ -1505,7 +1508,7 @@ static bool parse_sya_operand(parser_t *parser, shunt *sy, bool with_labels) parseerror(parser, "expected a constant string in translatable-string extension"); return false; } - val = (ast_value*)fold_constgen_string(parser->fold, parser_tokval(parser), true); + val = (ast_value*)parser->m_fold.constgen_string(parser_tokval(parser), true); if (!val) return false; sy->out.push_back(syexp(parser_ctx(parser), (ast_expression*)val)); @@ -1530,28 +1533,28 @@ static bool parse_sya_operand(parser_t *parser, shunt *sy, bool with_labels) return true; } else if (parser->tok == TOKEN_FLOATCONST) { - ast_expression *val = fold_constgen_float(parser->fold, (parser_token(parser)->constval.f), false); + ast_expression *val = parser->m_fold.constgen_float((parser_token(parser)->constval.f), false); if (!val) return false; sy->out.push_back(syexp(parser_ctx(parser), val)); return true; } else if (parser->tok == TOKEN_INTCONST || parser->tok == TOKEN_CHARCONST) { - ast_expression *val = fold_constgen_float(parser->fold, (qcfloat_t)(parser_token(parser)->constval.i), false); + ast_expression *val = parser->m_fold.constgen_float((qcfloat_t)(parser_token(parser)->constval.i), false); if (!val) return false; sy->out.push_back(syexp(parser_ctx(parser), val)); return true; } else if (parser->tok == TOKEN_STRINGCONST) { - ast_expression *val = fold_constgen_string(parser->fold, parser_tokval(parser), false); + ast_expression *val = parser->m_fold.constgen_string(parser_tokval(parser), false); if (!val) return false; sy->out.push_back(syexp(parser_ctx(parser), val)); return true; } else if (parser->tok == TOKEN_VECTORCONST) { - ast_expression *val = fold_constgen_vector(parser->fold, parser_token(parser)->constval.v); + ast_expression *val = parser->m_fold.constgen_vector(parser_token(parser)->constval.v); if (!val) return false; sy->out.push_back(syexp(parser_ctx(parser), val)); @@ -1587,7 +1590,7 @@ static bool parse_sya_operand(parser_t *parser, shunt *sy, bool with_labels) } } if (!var && !strcmp(parser_tokval(parser), "__FUNC__")) - var = (ast_expression*)fold_constgen_string(parser->fold, parser->function->name, false); + var = (ast_expression*)parser->m_fold.constgen_string(parser->function->name, false); if (!var) { /* * now we try for the real intrinsic hashtable. If the string @@ -1891,7 +1894,7 @@ static ast_expression* parse_expression_leave(parser_t *parser, bool stopatcomma { char *newstr = nullptr; util_asprintf(&newstr, "%s%s", last->constval.vstring, parser_tokval(parser)); - sy.out.back().out = (ast_expression*)fold_constgen_string(parser->fold, newstr, false); + sy.out.back().out = (ast_expression*)parser->m_fold.constgen_string(newstr, false); mem_d(newstr); concatenated = true; } @@ -3951,7 +3954,7 @@ static bool parse_function_body(parser_t *parser, ast_value *var) self_think = (ast_expression*)ast_entfield_new(ctx, gbl_self, fld_think); time_plus_1 = (ast_expression*)ast_binary_new(ctx, INSTR_ADD_F, - gbl_time, (ast_expression*)fold_constgen_float(parser->fold, frame_delta, false)); + gbl_time, (ast_expression*)parser->m_fold.constgen_float(frame_delta, false)); if (!self_frame || !self_nextthink || !self_think || !time_plus_1) { if (self_frame) ast_delete(self_frame); @@ -4076,7 +4079,7 @@ static bool parse_function_body(parser_t *parser, ast_value *var) goto enderrfn; } func->varargs = varargs; - func->fixedparams = (ast_value*)fold_constgen_float(parser->fold, var->expression.params.size(), false); + func->fixedparams = (ast_value*)parser->m_fold.constgen_float(var->expression.params.size(), false); } parser->function = func; @@ -4134,7 +4137,7 @@ static ast_expression *array_accessor_split( cmp = ast_binary_new(ctx, INSTR_LT, (ast_expression*)index, - (ast_expression*)fold_constgen_float(parser->fold, middle, false)); + (ast_expression*)parser->m_fold.constgen_float(middle, false)); if (!cmp) { ast_delete(left); ast_delete(right); @@ -4167,7 +4170,7 @@ static ast_expression *array_setter_node(parser_t *parser, ast_value *array, ast if (value->expression.vtype == TYPE_FIELD && value->expression.next->vtype == TYPE_VECTOR) assignop = INSTR_STORE_V; - subscript = ast_array_index_new(ctx, (ast_expression*)array, (ast_expression*)fold_constgen_float(parser->fold, from, false)); + subscript = ast_array_index_new(ctx, (ast_expression*)array, (ast_expression*)parser->m_fold.constgen_float(from, false)); if (!subscript) return nullptr; @@ -4233,7 +4236,7 @@ static ast_expression *array_field_setter_node( if (value->expression.vtype == TYPE_FIELD && value->expression.next->vtype == TYPE_VECTOR) assignop = INSTR_STOREP_V; - subscript = ast_array_index_new(ctx, (ast_expression*)array, (ast_expression*)fold_constgen_float(parser->fold, from, false)); + subscript = ast_array_index_new(ctx, (ast_expression*)array, (ast_expression*)parser->m_fold.constgen_float(from, false)); if (!subscript) return nullptr; @@ -4296,7 +4299,7 @@ static ast_expression *array_getter_node(parser_t *parser, ast_value *array, ast ast_return *ret; ast_array_index *subscript; - subscript = ast_array_index_new(ctx, (ast_expression*)array, (ast_expression*)fold_constgen_float(parser->fold, from, false)); + subscript = ast_array_index_new(ctx, (ast_expression*)array, (ast_expression*)parser->m_fold.constgen_float(from, false)); if (!subscript) return nullptr; @@ -6017,7 +6020,7 @@ parser_t *parser_create() parser->reserved_version = nullptr; } - parser->fold = fold_init(parser); + parser->m_fold = fold(parser); parser->m_intrin = intrin(parser); return parser; } @@ -6115,7 +6118,6 @@ static void parser_remove_ast(parser_t *parser) ast_value_delete(parser->reserved_version); util_htdel(parser->aliases); - fold_cleanup(parser->fold); } void parser_cleanup(parser_t *parser) @@ -6243,7 +6245,7 @@ bool parser_finish(parser_t *parser, const char *output) } } /* Now we can generate immediates */ - if (!fold_generate(parser->fold, ir)) + if (!parser->m_fold.generate(ir)) return false; /* before generating any functions we need to set the coverage_func */ diff --git a/parser.h b/parser.h index f9f0ab5..a09238d 100644 --- a/parser.h +++ b/parser.h @@ -2,20 +2,13 @@ #define GMQCC_PARSER_HDR #include "gmqcc.h" #include "lexer.h" -#include "ast.h" +//#include "ast.h" + #include "intrin.h" +#include "fold.h" struct parser_t; -struct fold_t { - parser_t *parser; - std::vector imm_float; - std::vector imm_vector; - std::vector imm_string; - hash_table_t *imm_string_untranslate; /* map */ - hash_table_t *imm_string_dotranslate; /* map */ -}; - #define parser_ctx(p) ((p)->lex->tok.ctx) struct parser_t { @@ -76,7 +69,7 @@ struct parser_t { /* collected information */ size_t max_param_count; - fold_t *fold; + fold m_fold; intrin m_intrin; }; @@ -85,18 +78,4 @@ struct parser_t { char *parser_strdup (const char *str); ast_expression *parser_find_global(parser_t *parser, const char *name); -/* fold.c */ -fold_t *fold_init (parser_t *); -void fold_cleanup (fold_t *); -ast_expression *fold_constgen_float (fold_t *, qcfloat_t, bool); -ast_expression *fold_constgen_vector(fold_t *, vec3_t); -ast_expression *fold_constgen_string(fold_t *, const char *, bool); -bool fold_generate (fold_t *, ir_builder *); -ast_expression *fold_op (fold_t *, const oper_info *, ast_expression **); -ast_expression *fold_intrin (fold_t *, const char *, ast_expression **); - -ast_expression *fold_binary (lex_ctx_t ctx, int, ast_expression *, ast_expression *); -int fold_cond_ifthen (ir_value *, ast_function *, ast_ifthen *); -int fold_cond_ternary (ir_value *, ast_function *, ast_ternary *); - #endif -- 2.39.2