]> git.xonotic.org Git - xonotic/gmqcc.git/commitdiff
constant folding for +, - and *
authorWolfgang (Blub) Bumiller <blub@speed.at>
Tue, 14 Aug 2012 20:51:05 +0000 (22:51 +0200)
committerWolfgang (Blub) Bumiller <blub@speed.at>
Tue, 14 Aug 2012 20:51:05 +0000 (22:51 +0200)
gmqcc.h
parser.c

diff --git a/gmqcc.h b/gmqcc.h
index eb3958807929c49b36659e209f5249e3daecb14e..8c097672351ffb4cffa5a127c5788f450059cec3 100644 (file)
--- a/gmqcc.h
+++ b/gmqcc.h
@@ -780,6 +780,11 @@ typedef struct {
     float x, y, z;
 } vector;
 
+vector  vec3_add  (vector, vector);
+vector  vec3_sub  (vector, vector);
+qcfloat vec3_mulvv(vector, vector);
+vector  vec3_mulvf(vector, float);
+
 /*
  * A shallow copy of a lex_file to remember where which ast node
  * came from.
index 27e7f707abddd1ec39fd2fcb20f30c04b655ab4d..9887978771faf9f8f6488f1203668b87d91efb6b 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -82,6 +82,46 @@ bool GMQCC_WARN parsewarning(parser_t *parser, int warntype, const char *fmt, ..
        return OPTS_WARN(WARN_ERROR);
 }
 
+/**********************************************************************
+ * some maths used for constant folding
+ */
+
+vector vec3_add(vector a, vector b)
+{
+    vector out;
+    out.x = a.x + b.x;
+    out.y = a.y + b.y;
+    out.z = a.z + b.z;
+    return out;
+}
+
+vector vec3_sub(vector a, vector b)
+{
+    vector out;
+    out.x = a.x - b.x;
+    out.y = a.y - b.y;
+    out.z = a.z - b.z;
+    return out;
+}
+
+qcfloat vec3_mulvv(vector a, vector b)
+{
+    return (a.x * b.x + a.y * b.y + a.z * b.z);
+}
+
+vector vec3_mulvf(vector a, float b)
+{
+    vector out;
+    out.x = a.x * b;
+    out.y = a.y * b;
+    out.z = a.z * b;
+    return out;
+}
+
+/**********************************************************************
+ * parsing
+ */
+
 bool parser_next(parser_t *parser)
 {
     /* lex_do kills the previous token */
@@ -349,6 +389,7 @@ static bool parser_sy_pop(parser_t *parser, shunt *sy)
     ast_expression *out = NULL;
     ast_expression *exprs[3];
     ast_block      *blocks[3];
+    ast_value      *asvalue[3];
     size_t i, assignop;
     qcint  generated_op = 0;
 
@@ -378,6 +419,7 @@ static bool parser_sy_pop(parser_t *parser, shunt *sy)
     for (i = 0; i < op->operands; ++i) {
         exprs[i]  = sy->out[sy->out_count+i].out;
         blocks[i] = sy->out[sy->out_count+i].block;
+        asvalue[i] = (ast_value*)exprs[i];
     }
 
     if (blocks[0] && !blocks[0]->exprs_count && op->id != opid1(',')) {
@@ -388,6 +430,9 @@ static bool parser_sy_pop(parser_t *parser, shunt *sy)
 #define NotSameType(T) \
              (exprs[0]->expression.vtype != exprs[1]->expression.vtype || \
               exprs[0]->expression.vtype != T)
+#define CanConstFold(A, B)                                                \
+             (ast_istype((A), ast_value) && ast_istype((B), ast_value) && \
+              ((ast_value*)(A))->isconst && ((ast_value*)(B))->isconst)
     switch (op->id)
     {
         default:
@@ -441,10 +486,22 @@ static bool parser_sy_pop(parser_t *parser, shunt *sy)
             }
             switch (exprs[0]->expression.vtype) {
                 case TYPE_FLOAT:
-                    out = (ast_expression*)ast_binary_new(ctx, INSTR_ADD_F, exprs[0], exprs[1]);
+                    if (CanConstFold(exprs[0], exprs[1]))
+                    {
+                        out = (ast_expression*)parser_const_float(parser,
+                            asvalue[0]->constval.vfloat + asvalue[1]->constval.vfloat);
+                    }
+                    else
+                        out = (ast_expression*)ast_binary_new(ctx, INSTR_ADD_F, exprs[0], exprs[1]);
                     break;
                 case TYPE_VECTOR:
-                    out = (ast_expression*)ast_binary_new(ctx, INSTR_ADD_V, exprs[0], exprs[1]);
+                    if (CanConstFold(exprs[0], exprs[1]))
+                    {
+                        out = (ast_expression*)parser_const_vector(parser,
+                            vec3_add(asvalue[0]->constval.vvec, asvalue[1]->constval.vvec));
+                    }
+                    else
+                        out = (ast_expression*)ast_binary_new(ctx, INSTR_ADD_V, exprs[0], exprs[1]);
                     break;
                 default:
                     parseerror(parser, "invalid types used in expression: cannot add type %s and %s",
@@ -464,10 +521,22 @@ static bool parser_sy_pop(parser_t *parser, shunt *sy)
             }
             switch (exprs[0]->expression.vtype) {
                 case TYPE_FLOAT:
-                    out = (ast_expression*)ast_binary_new(ctx, INSTR_SUB_F, exprs[0], exprs[1]);
+                    if (CanConstFold(exprs[0], exprs[1]))
+                    {
+                        out = (ast_expression*)parser_const_float(parser,
+                            asvalue[0]->constval.vfloat - asvalue[1]->constval.vfloat);
+                    }
+                    else
+                        out = (ast_expression*)ast_binary_new(ctx, INSTR_SUB_F, exprs[0], exprs[1]);
                     break;
                 case TYPE_VECTOR:
-                    out = (ast_expression*)ast_binary_new(ctx, INSTR_SUB_V, exprs[0], exprs[1]);
+                    if (CanConstFold(exprs[0], exprs[1]))
+                    {
+                        out = (ast_expression*)parser_const_vector(parser,
+                            vec3_sub(asvalue[0]->constval.vvec, asvalue[1]->constval.vvec));
+                    }
+                    else
+                        out = (ast_expression*)ast_binary_new(ctx, INSTR_SUB_V, exprs[0], exprs[1]);
                     break;
                 default:
                     parseerror(parser, "invalid types used in expression: cannot subtract type %s from %s",
@@ -491,15 +560,39 @@ static bool parser_sy_pop(parser_t *parser, shunt *sy)
             switch (exprs[0]->expression.vtype) {
                 case TYPE_FLOAT:
                     if (exprs[1]->expression.vtype == TYPE_VECTOR)
-                        out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_FV, exprs[0], exprs[1]);
+                    {
+                        if (CanConstFold(exprs[0], exprs[1]))
+                            out = (ast_expression*)parser_const_vector(parser,
+                                vec3_mulvf(asvalue[1]->constval.vvec, asvalue[0]->constval.vfloat));
+                        else
+                            out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_FV, exprs[0], exprs[1]);
+                    }
                     else
-                        out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_F, exprs[0], exprs[1]);
+                    {
+                        if (CanConstFold(exprs[0], exprs[1]))
+                            out = (ast_expression*)parser_const_float(parser,
+                                asvalue[0]->constval.vfloat * asvalue[1]->constval.vfloat);
+                        else
+                            out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_F, exprs[0], exprs[1]);
+                    }
                     break;
                 case TYPE_VECTOR:
                     if (exprs[1]->expression.vtype == TYPE_FLOAT)
-                        out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_VF, exprs[0], exprs[1]);
+                    {
+                        if (CanConstFold(exprs[0], exprs[1]))
+                            out = (ast_expression*)parser_const_vector(parser,
+                                vec3_mulvf(asvalue[0]->constval.vvec, asvalue[1]->constval.vfloat));
+                        else
+                            out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_VF, exprs[0], exprs[1]);
+                    }
                     else
-                        out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_V, exprs[0], exprs[1]);
+                    {
+                        if (CanConstFold(exprs[0], exprs[1]))
+                            out = (ast_expression*)parser_const_float(parser,
+                                vec3_mulvv(asvalue[0]->constval.vvec, asvalue[1]->constval.vvec));
+                        else
+                            out = (ast_expression*)ast_binary_new(ctx, INSTR_MUL_V, exprs[0], exprs[1]);
+                    }
                     break;
                 default:
                     parseerror(parser, "invalid types used in expression: cannot multiply types %s and %s",