Make unary - operator act as an ast_unary node. This allows for consistency (no sense...
authorDale Weiler <killfieldengine@gmail.com>
Mon, 30 Sep 2013 02:01:46 +0000 (22:01 -0400)
committerDale Weiler <killfieldengine@gmail.com>
Mon, 30 Sep 2013 02:01:46 +0000 (22:01 -0400)
ast.c
gmqcc.h
ir.c
parser.c

diff --git a/ast.c b/ast.c
index 3f5f02b5e5f4319a291121f57ab2e5afaa03c20b..ad85e4fec6bc4d38ab3a360c0254eb8f48070b82 100644 (file)
--- a/ast.c
+++ b/ast.c
@@ -515,7 +515,7 @@ ast_unary* ast_unary_new(lex_ctx_t ctx, int op,
     ast_instantiate(ast_unary, ctx, ast_unary_delete);
     ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_unary_codegen);
 
-    self->op = op;
+    self->op      = op;
     self->operand = expr;
 
     if (ast_istype(expr, ast_unary) && OPTS_OPTIMIZATION(OPTIM_PEEPHOLE)) {
@@ -530,10 +530,13 @@ ast_unary* ast_unary_new(lex_ctx_t ctx, int op,
 
     ast_propagate_effects(self, expr);
 
-    if (op >= INSTR_NOT_F && op <= INSTR_NOT_FNC) {
+    if (op >= INSTR_NOT_F  && op <= INSTR_NOT_FNC) {
         self->expression.vtype = TYPE_FLOAT;
-    } else
+    } else if (op >= VINSTR_NEG_F && op <= VINSTR_NEG_V) {
+        self->expression.vtype = TYPE_FLOAT;
+    } else {
         compile_error(ctx, "cannot determine type of unary operation %s", util_instr_str[op]);
+    }
 
     return self;
 }
diff --git a/gmqcc.h b/gmqcc.h
index d8ad37465ef0525ea2298a9eb484f7a6e9220f04..9848f20bbc19067d69cc0043e523fb7a4abe3236 100644 (file)
--- a/gmqcc.h
+++ b/gmqcc.h
@@ -712,6 +712,7 @@ enum {
     VINSTR_PHI,
     VINSTR_JUMP,
     VINSTR_COND,
+
     /* A never returning CALL.
      * Creating this causes IR blocks to be marked as 'final'.
      * No-Return-Call
@@ -726,7 +727,9 @@ enum {
     VINSTR_BITXOR,
     VINSTR_BITXOR_V,
     VINSTR_BITXOR_VF,
-    VINSTR_CROSS
+    VINSTR_CROSS,
+    VINSTR_NEG_F,
+    VINSTR_NEG_V
 };
 
 /* TODO: elide */
diff --git a/ir.c b/ir.c
index f92d5524eb12281e4d13fe1044f906e150718e41..49d4b2f02e26354024e1db26da4765bbb639c78f 100644 (file)
--- a/ir.c
+++ b/ir.c
@@ -1878,16 +1878,22 @@ ir_value* ir_block_create_unary(ir_block *self, lex_ctx_t ctx,
         case INSTR_NOT_V:
         case INSTR_NOT_S:
         case INSTR_NOT_ENT:
-        case INSTR_NOT_FNC:
-#if 0
-        case INSTR_NOT_I:
-#endif
+        case INSTR_NOT_FNC: /*
+        case INSTR_NOT_I:   */
             ot = TYPE_FLOAT;
             break;
-        /* QC doesn't have other unary operations. We expect extensions to fill
-         * the above list, otherwise we assume out-type = in-type, eg for an
-         * unary minus
+
+        /*
+         * Negation for virtual instructions is emulated with 0-value. Thankfully
+         * the operand for 0 already exists so we just source it from here.
          */
+        case VINSTR_NEG_F:
+            return ir_block_create_general_instr(self, ctx, label, INSTR_SUB_F, NULL, operand, ot);
+            break;
+        case VINSTR_NEG_V:
+            return ir_block_create_general_instr(self, ctx, label, INSTR_SUB_V, NULL, operand, ot);
+            break;
+
         default:
             ot = operand->vtype;
             break;
index bfc8be4410d2d17e369e10dc25fe93467997e6d7..7d4698e331c45d8558197f70d1c0b8905ee66cee 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -466,22 +466,18 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
             break;
         case opid2('-','P'):
             if (!(out = fold_op(parser->fold, op, exprs))) {
-                switch (exprs[0]->vtype) {
-                    case TYPE_FLOAT:
-                        out = (ast_expression*)ast_binary_new(ctx, INSTR_SUB_F,
-                                                                  (ast_expression*)parser->fold->imm_float[0],
-                                                                  exprs[0]);
-                        break;
-                    case TYPE_VECTOR:
-                        out = (ast_expression*)ast_binary_new(ctx, INSTR_SUB_V,
-                                                                  (ast_expression*)parser->fold->imm_vector[0],
-                                                                  exprs[0]);
-                        break;
-                    default:
-                    compile_error(ctx, "invalid types used in expression: cannot negate type %s",
-                                  type_name[exprs[0]->vtype]);
+                if (exprs[0]->vtype != TYPE_FLOAT &&
+                    exprs[0]->vtype != TYPE_VECTOR) {
+                        compile_error(ctx, "invalid types used in unary expression: cannot negate type %s",
+                                      type_name[exprs[0]->vtype]);
                     return false;
                 }
+                /*
+                 * TYPE_VECTOR  = TYPE_FLOAT+1,
+                 * VINSTR_NEG_V = VINSTR_NEG_F+1,
+                 * thus (VINSTR_NEG_F-TYPE_FLOAT) + TYPE_* = VINSTR_NEG_*.
+                 */
+                out = (ast_expression*)ast_unary_new(ctx, (VINSTR_NEG_F-TYPE_FLOAT) + exprs[0]->vtype, exprs[0]);
             }
             break;