return bytecode_push(&ctx->bytecode, &insn, 1, sizeof(insn));
}
-static
-enum filter_register reg_sel(struct ir_op *node)
-{
- switch (node->side) {
- case IR_SIDE_UNKNOWN:
- default:
- fprintf(stderr, "[error] Unknown node side in %s\n",
- __func__);
- return REG_ERROR;
- case IR_LEFT:
- return REG_R0;
- case IR_RIGHT:
- return REG_R1;
- }
-}
-
static
int visit_node_load(struct filter_parser_ctx *ctx, struct ir_op *node)
{
if (!insn)
return -ENOMEM;
insn->op = FILTER_OP_LOAD_STRING;
- insn->reg = reg_sel(node);
- if (insn->reg == REG_ERROR)
- return -EINVAL;
strcpy(insn->data, node->u.load.u.string);
ret = bytecode_push(&ctx->bytecode, insn, 1, insn_len);
free(insn);
if (!insn)
return -ENOMEM;
insn->op = FILTER_OP_LOAD_S64;
- insn->reg = reg_sel(node);
- if (insn->reg == REG_ERROR)
- return -EINVAL;
*(int64_t *) insn->data = node->u.load.u.num;
ret = bytecode_push(&ctx->bytecode, insn, 1, insn_len);
free(insn);
if (!insn)
return -ENOMEM;
insn->op = FILTER_OP_LOAD_DOUBLE;
- insn->reg = reg_sel(node);
- if (insn->reg == REG_ERROR)
- return -EINVAL;
*(double *) insn->data = node->u.load.u.flt;
ret = bytecode_push(&ctx->bytecode, insn, 1, insn_len);
free(insn);
if (!insn)
return -ENOMEM;
insn->op = FILTER_OP_LOAD_FIELD_REF;
- insn->reg = reg_sel(node);
ref_offset.offset = (uint16_t) -1U;
memcpy(insn->data, &ref_offset, sizeof(ref_offset));
- if (insn->reg == REG_ERROR)
- return -EINVAL;
/* reloc_offset points to struct load_op */
reloc_offset = bytecode_get_len(&ctx->bytecode->b);
ret = bytecode_push(&ctx->bytecode, insn, 1, insn_len);
return 0;
case AST_UNARY_MINUS:
insn.op = FILTER_OP_UNARY_MINUS;
- insn.reg = reg_sel(node);
- if (insn.reg == REG_ERROR)
- return -EINVAL;
return bytecode_push(&ctx->bytecode, &insn, 1, sizeof(insn));
case AST_UNARY_NOT:
insn.op = FILTER_OP_UNARY_NOT;
- insn.reg = reg_sel(node);
- if (insn.reg == REG_ERROR)
- return -EINVAL;
return bytecode_push(&ctx->bytecode, &insn, 1, sizeof(insn));
}
}
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;
+
+ if (node->u.binary.left->data_type == IR_DATA_FIELD_REF) {
+ cast_insn.op = FILTER_OP_CAST_TO_S64;
+ } else {
+ cast_insn.op = FILTER_OP_CAST_DOUBLE_TO_S64;
+ }
+ 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;
+
+ if (node->u.binary.right->data_type == IR_DATA_FIELD_REF) {
+ cast_insn.op = FILTER_OP_CAST_TO_S64;
+ } else {
+ cast_insn.op = FILTER_OP_CAST_DOUBLE_TO_S64;
+ }
+ 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,