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)) {
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;
}
VINSTR_PHI,
VINSTR_JUMP,
VINSTR_COND,
+
/* A never returning CALL.
* Creating this causes IR blocks to be marked as 'final'.
* No-Return-Call
VINSTR_BITXOR,
VINSTR_BITXOR_V,
VINSTR_BITXOR_VF,
- VINSTR_CROSS
+ VINSTR_CROSS,
+ VINSTR_NEG_F,
+ VINSTR_NEG_V
};
/* TODO: elide */
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;
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;