Filter: cast double directly to s64
[lttng-tools.git] / src / lib / lttng-ctl / filter-visitor-generate-bytecode.c
index e940e2c81ab6f85ea8313018d58f5fc7d51f8e6e..a9e741cd21ae2983dbb1ba28d949bbb6e01643e6 100644 (file)
@@ -39,9 +39,9 @@ int recursive_visit_gen_bytecode(struct filter_parser_ctx *ctx,
                struct ir_op *node);
 
 static
-int bytecode_init(struct filter_bytecode_alloc **fb)
+int bytecode_init(struct lttng_filter_bytecode_alloc **fb)
 {
-       *fb = calloc(sizeof(struct filter_bytecode_alloc) + INIT_ALLOC_SIZE, 1);
+       *fb = calloc(sizeof(struct lttng_filter_bytecode_alloc) + INIT_ALLOC_SIZE, 1);
        if (!*fb) {
                return -ENOMEM;
        } else {
@@ -51,7 +51,7 @@ int bytecode_init(struct filter_bytecode_alloc **fb)
 }
 
 static
-int32_t bytecode_reserve(struct filter_bytecode_alloc **fb, uint32_t align, uint32_t len)
+int32_t bytecode_reserve(struct lttng_filter_bytecode_alloc **fb, uint32_t align, uint32_t len)
 {
        int32_t ret;
        uint32_t padding = offset_align((*fb)->b.len, align);
@@ -64,7 +64,7 @@ int32_t bytecode_reserve(struct filter_bytecode_alloc **fb, uint32_t align, uint
 
                if (new_len > 0xFFFF)
                        return -EINVAL;
-               *fb = realloc(*fb, sizeof(struct filter_bytecode_alloc) + new_len);
+               *fb = realloc(*fb, sizeof(struct lttng_filter_bytecode_alloc) + new_len);
                if (!*fb)
                        return -ENOMEM;
                memset(&(*fb)->b.data[old_len], 0, new_len - old_len);
@@ -77,7 +77,7 @@ int32_t bytecode_reserve(struct filter_bytecode_alloc **fb, uint32_t align, uint
 }
 
 static
-int bytecode_push(struct filter_bytecode_alloc **fb, const void *data,
+int bytecode_push(struct lttng_filter_bytecode_alloc **fb, const void *data,
                uint32_t align, uint32_t len)
 {
        int32_t offset;
@@ -90,7 +90,7 @@ int bytecode_push(struct filter_bytecode_alloc **fb, const void *data,
 }
 
 static
-int bytecode_push_logical(struct filter_bytecode_alloc **fb,
+int bytecode_push_logical(struct lttng_filter_bytecode_alloc **fb,
                struct logical_op *data,
                uint32_t align, uint32_t len,
                uint16_t *skip_offset)
@@ -108,7 +108,7 @@ int bytecode_push_logical(struct filter_bytecode_alloc **fb,
 }
 
 static
-int bytecode_patch(struct filter_bytecode_alloc **fb,
+int bytecode_patch(struct lttng_filter_bytecode_alloc **fb,
                const void *data,
                uint16_t offset,
                uint32_t len)
@@ -200,6 +200,24 @@ int visit_node_load(struct filter_parser_ctx *ctx, struct ir_op *node)
                free(insn);
                return ret;
        }
+       case IR_DATA_FLOAT:
+       {
+               struct load_op *insn;
+               uint32_t insn_len = sizeof(struct load_op)
+                       + sizeof(struct literal_double);
+
+               insn = calloc(insn_len, 1);
+               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);
+               return ret;
+       }
        case IR_DATA_FIELD_REF:
        {
                struct load_op *insn;
@@ -217,9 +235,8 @@ int visit_node_load(struct filter_parser_ctx *ctx, struct ir_op *node)
                memcpy(insn->data, &ref_offset, sizeof(ref_offset));
                if (insn->reg == REG_ERROR)
                        return -EINVAL;
-               /* reloc_offset points to struct field_ref */
+               /* reloc_offset points to struct load_op */
                reloc_offset = bytecode_get_len(&ctx->bytecode->b);
-               reloc_offset += sizeof(struct load_op);
                ret = bytecode_push(&ctx->bytecode, insn, 1, insn_len);
                if (ret) {
                        free(insn);
@@ -360,6 +377,9 @@ int visit_node_binary(struct filter_parser_ctx *ctx, struct ir_op *node)
        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)
 {
@@ -372,6 +392,22 @@ 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;
+               }
+               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",
@@ -394,6 +430,22 @@ int visit_node_logical(struct filter_parser_ctx *ctx, struct ir_op *node)
        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;
+               }
+               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,
This page took 0.025144 seconds and 4 git commands to generate.