/* logical */
FILTER_OP_AND,
FILTER_OP_OR,
- FILTER_OP_AND_S64,
- FILTER_OP_OR_S64,
- FILTER_OP_AND_DOUBLE,
- FILTER_OP_OR_DOUBLE,
/* load */
FILTER_OP_LOAD_FIELD_REF,
FILTER_OP_LOAD_S64,
FILTER_OP_LOAD_DOUBLE,
+ /* cast */
+ FILTER_OP_CAST_TO_S64,
+ FILTER_OP_CAST_DOUBLE_TO_S64,
+ FILTER_OP_CAST_NOP,
+
NR_FILTER_OPS,
};
uint16_t skip_offset; /* bytecode insn, if skip second test */
} __attribute__((packed));
+struct cast_op {
+ filter_opcode_t op;
+ uint8_t reg; /* enum filter_register */
+} __attribute__((packed));
+
struct return_op {
filter_opcode_t op;
} __attribute__((packed));
return bytecode_push(&ctx->bytecode, &insn, 1, sizeof(insn));
}
+/*
+ * A logical op always return a s64 (1 or 0).
+ */
static
int visit_node_logical(struct filter_parser_ctx *ctx, struct ir_op *node)
{
ret = recursive_visit_gen_bytecode(ctx, node->u.binary.left);
if (ret)
return ret;
+ /* Cast to s64 if float or field ref */
+ if (node->u.binary.left->data_type == IR_DATA_FIELD_REF
+ || node->u.binary.left->data_type == IR_DATA_FLOAT) {
+ struct cast_op cast_insn;
+
+ cast_insn.op = FILTER_OP_CAST_TO_S64;
+ cast_insn.reg = REG_R0;
+ ret = bytecode_push(&ctx->bytecode, &cast_insn,
+ 1, sizeof(cast_insn));
+ if (ret)
+ return ret;
+ }
switch (node->u.logical.type) {
default:
fprintf(stderr, "[error] Unknown node type in %s\n",
ret = recursive_visit_gen_bytecode(ctx, node->u.binary.right);
if (ret)
return ret;
+ /* Cast to s64 if float or field ref */
+ if (node->u.binary.right->data_type == IR_DATA_FIELD_REF
+ || node->u.binary.right->data_type == IR_DATA_FLOAT) {
+ struct cast_op cast_insn;
+
+ cast_insn.op = FILTER_OP_CAST_TO_S64;
+ cast_insn.reg = REG_R0;
+ ret = bytecode_push(&ctx->bytecode, &cast_insn,
+ 1, sizeof(cast_insn));
+ if (ret)
+ return ret;
+ }
/* We now know where the logical op can skip. */
target_loc = (uint16_t) bytecode_get_len(&ctx->bytecode->b);
ret = bytecode_patch(&ctx->bytecode,