Add optional type
authorOlivier Dion <odion@efficios.com>
Tue, 15 Oct 2024 16:27:50 +0000 (12:27 -0400)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Wed, 23 Oct 2024 16:08:41 +0000 (12:08 -0400)
The `SIDE_TYPE_OPTIONAL' denotes a field that can be absent from the
trace.  Such field has no attribute.  Instead, the optional type is
simply a pointer to another type.

The determination of absence for an optional field is determined by the
`selector' member of the `side_arg_optional' structure, which must be
the constant value `SIDE_OPTIONAL_ENABLED' if the field is present,
otherwise `SIDE_OPTION_DISABLED'.

Change-Id: Ie23bcac27efef66938981d59b715a950465ede75
Signed-off-by: Olivier Dion <odion@efficios.com>
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
include/side/abi/type-argument.h
include/side/abi/type-description.h
include/side/instrumentation-c-api.h
src/tracer.c
src/visit-arg-vec.c
src/visit-description.c
src/visit-description.h
tests/unit/test.c

index 57ce5252fcde9bd854a5a0d103fbb1ce099f5670..4d3cb6f85bb30dee3ea030fb8449e50041ac2230 100644 (file)
@@ -79,6 +79,7 @@ union side_arg_static {
        /* Stack-copy compound types */
        side_ptr_t(const struct side_arg_vec) side_struct;
        side_ptr_t(const struct side_arg_variant) side_variant;
+       side_ptr_t(const struct side_arg_optional) side_optional;
        side_ptr_t(const struct side_arg_vec) side_array;
        side_ptr_t(const struct side_arg_vec) side_vla;
        /* Pointer to non-const structure. Content modified by libside. */
@@ -192,6 +193,12 @@ struct side_arg_variant {
 } SIDE_PACKED;
 side_check_size(struct side_arg_variant, 128);
 
+struct side_arg_optional {
+       struct side_arg side_static;
+       uint8_t selector;
+} SIDE_PACKED;
+side_check_size(struct side_arg_optional, 65);
+
 struct side_arg_vec {
        side_ptr_t(const struct side_arg) sav;
        uint32_t len;
index 60868570c5835fd79701b7867d0beb8a5a70494d..aa30485350dc8d445d78737b9ecf40212094a6e4 100644 (file)
@@ -109,6 +109,7 @@ enum side_type_label {
        /* Stack-copy compound types */
        SIDE_TYPE_STRUCT,
        SIDE_TYPE_VARIANT,
+       SIDE_TYPE_OPTIONAL,
        SIDE_TYPE_ARRAY,
        SIDE_TYPE_VLA,
        SIDE_TYPE_VLA_VISITOR,
@@ -382,6 +383,7 @@ struct side_type {
                side_ptr_t(const struct side_type_vla_visitor) side_vla_visitor;
                side_ptr_t(const struct side_type_struct) side_struct;
                side_ptr_t(const struct side_type_variant) side_variant;
+               side_ptr_t(const struct side_type) side_optional;
 
                /* Stack-copy enumeration types */
                struct side_type_enum side_enum;
index 2e17d49fa5b9c5a33dbe6cfde23c2c2e0d5a096e..57f22eae322d8cf5843c06d2e711f933f4899b06 100644 (file)
        const struct side_type_variant _identifier = \
                _side_type_variant_define(SIDE_PARAM(_selector), SIDE_PARAM(_options), SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list()))
 
-#define side_variant_literal(_selector, _options, _attr...) \
-       SIDE_COMPOUND_LITERAL(const struct side_type_variant, \
-               _side_type_variant_define(SIDE_PARAM(_selector), SIDE_PARAM(_options), SIDE_PARAM_SELECT_ARG1(_, ##_attr, side_attr_list())))
+enum {
+       SIDE_OPTIONAL_DISABLED = 0,
+       SIDE_OPTIONAL_ENABLED = 1,
+};
+
+#define side_type_optional(_type)                              \
+       {                                                       \
+               .type = SIDE_ENUM_INIT(SIDE_TYPE_OPTIONAL),     \
+               .u = {                                          \
+                       .side_optional = SIDE_PTR_INIT(_type),  \
+               },                                              \
+       }
+
+#define side_define_optional(_identifier, _type)       \
+       const struct side_type _identifier = side_type_optional(SIDE_PARAM(_type))
+
+#define side_field_optional(_name, _identifier)        \
+       _side_field(_name, side_type_optional(_identifier))
+
+#define side_field_optional_literal(_name, _type)                      \
+       _side_field(_name, side_type_optional(SIDE_PARAM(_type)))
 
 #define side_type_array(_elem_type, _length, _attr...) \
        { \
                }, \
        }
 
+
+#define side_arg_define_optional(_identifier, _value, _selector)       \
+       const struct side_arg_optional _identifier = {                  \
+               .side_static = _value,                                  \
+               .selector = _selector,                                  \
+       }
+
+#define side_arg_optional(_identifier)                                 \
+       {                                                               \
+               .type = SIDE_ENUM_INIT(SIDE_TYPE_OPTIONAL),             \
+               .flags = 0,                                             \
+               .u = {                                                  \
+                       .side_static = {                                \
+                               .side_optional = SIDE_PTR_INIT(_identifier) \
+                       },                                              \
+               },                                                      \
+       }
+
 #define side_arg_array(_side_type)     { .type = SIDE_ENUM_INIT(SIDE_TYPE_ARRAY), .flags = 0, .u = { .side_static = { .side_array = SIDE_PTR_INIT(_side_type) } } }
 #define side_arg_vla(_side_type)       { .type = SIDE_ENUM_INIT(SIDE_TYPE_VLA), .flags = 0, .u = { .side_static = { .side_vla = SIDE_PTR_INIT(_side_type) } } }
 #define side_arg_vla_visitor(_side_vla_visitor) \
index d8d6ba91434101eb27e58f5ffb7fc30218f36b45..ff24388b3dd405d9604ee64f72d129b634b3c382 100644 (file)
@@ -2057,6 +2057,25 @@ void after_print_description_variant(const struct side_type_variant *side_varian
        printf(" } }");
 }
 
+static
+void before_print_description_optional(const struct side_type *optional __attribute__((unused)),
+                               void *priv __attribute__((unused)))
+{
+       struct print_ctx *ctx = (struct print_ctx *) priv;
+
+       printf("type: optional {");
+       push_nesting(ctx);
+}
+
+static
+void after_print_description_optional(const struct side_type *optional __attribute__((unused)), void *priv)
+{
+       struct print_ctx *ctx = (struct print_ctx *) priv;
+
+       pop_nesting(ctx);
+       printf(" } }");
+}
+
 static
 void before_print_description_array(const struct side_type_array *side_array, void *priv)
 {
@@ -2495,6 +2514,8 @@ struct side_description_visitor description_visitor = {
        .before_vla_visitor_type_func = before_print_description_vla_visitor,
        .after_length_vla_visitor_type_func = after_length_print_description_vla_visitor,
        .after_element_vla_visitor_type_func = after_element_print_description_vla_visitor,
+       .before_optional_type_func = before_print_description_optional,
+       .after_optional_type_func = after_print_description_optional,
 
        /* Stack-copy enumeration types. */
        .before_enum_type_func = before_print_description_enum,
index 1942579c05a41201afba7548d6c5479d35b11d8e..bda94cc0daec8fee51ab9a03e9e217ebc2cbf671 100644 (file)
@@ -17,6 +17,7 @@ enum context_type {
        CONTEXT_FIELD,
        CONTEXT_ARRAY,
        CONTEXT_STRUCT,
+       CONTEXT_OPTIONAL,
 };
 
 struct visit_context {
@@ -337,6 +338,26 @@ void type_visitor_variant(const struct side_type_visitor *type_visitor, const st
        abort();
 }
 
+static
+void type_visitor_optional(const struct side_type_visitor *type_visitor, const struct visit_context *ctx,
+                       const struct side_type *type_desc, const struct side_arg_optional *side_arg_optional, void *priv)
+{
+       const struct side_type *type;
+       const struct side_arg *arg;
+       struct visit_context new_ctx = {
+               .type = CONTEXT_OPTIONAL,
+               .parent = ctx,
+       };
+
+       if (side_arg_optional->selector == SIDE_OPTIONAL_DISABLED)
+               return;
+
+       type = side_ptr_get(type_desc->u.side_optional);
+       arg = &side_arg_optional->side_static;
+
+       side_visit_type(type_visitor, &new_ctx, type, arg, priv);
+}
+
 static
 void type_visitor_array(const struct side_type_visitor *type_visitor, const struct visit_context *ctx,
                        const struct side_type *type_desc, const struct side_arg_vec *side_arg_vec, void *priv)
@@ -1022,6 +1043,9 @@ static size_t unwind_context(const struct visit_context *ctx, size_t indent)
        case CONTEXT_ARRAY:
                fprintf(stderr, "index: %zu", ctx->array_index);
                break;
+       case CONTEXT_OPTIONAL:
+               fprintf(stderr, "optional");
+               break;
        case CONTEXT_NAMESPACE: /* Fallthrough */
        default:
                abort();
@@ -1329,6 +1353,12 @@ void side_visit_type(const struct side_type_visitor *type_visitor,
                visit_dynamic_type(type_visitor, item, priv);
                break;
 
+       case SIDE_TYPE_OPTIONAL:
+               type_visitor_optional(type_visitor, ctx, type_desc,
+                               side_ptr_get(item->u.side_static.side_optional),
+                               priv);
+               break;
+
        default:
                fprintf(stderr, "<UNKNOWN TYPE>\n");
                abort();
index 84752899fe9b5ae8ba04e985edb4e8c3ea25c2d1..bbb69993ee3767107de30fab40259d6e913b59a2 100644 (file)
@@ -122,6 +122,19 @@ void description_visitor_variant(const struct side_description_visitor *descript
                description_visitor->after_variant_type_func(side_type_variant, priv);
 }
 
+static
+void description_visitor_optional(const struct side_description_visitor *description_visitor,
+                               const struct side_type *type_desc, void *priv)
+{
+       const struct side_type *optional = side_ptr_get(type_desc->u.side_optional);
+
+       if (description_visitor->before_optional_type_func)
+               description_visitor->before_optional_type_func(optional, priv);
+       side_visit_type(description_visitor, optional, priv);
+       if (description_visitor->after_optional_type_func)
+               description_visitor->after_optional_type_func(optional, priv);
+}
+
 static
 void description_visitor_array(const struct side_description_visitor *description_visitor, const struct side_type *type_desc, void *priv)
 {
@@ -468,6 +481,10 @@ void side_visit_type(const struct side_description_visitor *description_visitor,
                        description_visitor->dynamic_type_func(type_desc, priv);
                break;
 
+       case SIDE_TYPE_OPTIONAL:
+               description_visitor_optional(description_visitor, type_desc, priv);
+               break;
+
        default:
                fprintf(stderr, "<UNKNOWN TYPE>\n");
                abort();
index 3f9ae6bd093b2b0cea0c5c6c4c63cfc4bfe8d65c..d9a3597f35d452e895e1002a55260875e5f4c780 100644 (file)
@@ -44,6 +44,8 @@ struct side_description_visitor {
        void (*before_vla_visitor_type_func)(const struct side_type_vla_visitor *side_vla_visitor, void *priv);
        void (*after_length_vla_visitor_type_func)(const struct side_type_vla_visitor *side_vla_visitor, void *priv);
        void (*after_element_vla_visitor_type_func)(const struct side_type_vla_visitor *side_vla_visitor, void *priv);
+       void (*before_optional_type_func)(const struct side_type *optional, void *priv);
+       void (*after_optional_type_func)(const struct side_type *optional, void *priv);
 
        /* Stack-copy enumeration types. */
        void (*before_enum_type_func)(const struct side_type *type_desc, void *priv);
index d6b11ad0d0e04f8f91fae867788de140d42a55f7..90de62de29dd38bc02c83c09162b72736477d28a 100644 (file)
@@ -2288,6 +2288,31 @@ void test_c_native_types(void)
 #undef X
 }
 
+static side_define_optional(my_optional, side_elem(side_type_string()));
+
+side_static_event(my_provider_event_optional, "myprovider", "myeventoptional", SIDE_LOGLEVEL_DEBUG,
+       side_field_list(
+               side_field_optional("a", &my_optional),
+               side_field_optional_literal("b", side_elem(side_type_string())),
+       )
+);
+
+
+static
+void test_optional(void)
+{
+       if (side_event_enabled(my_provider_event_optional)) {
+               side_arg_define_optional(present, side_arg_string("present"), SIDE_OPTIONAL_ENABLED);
+               side_arg_define_optional(absent, side_arg_string("absent"), SIDE_OPTIONAL_DISABLED);
+
+               side_event_call(my_provider_event_optional,
+                       side_arg_list(
+                               side_arg_optional(&present),
+                               side_arg_optional(&absent),
+                       )
+               );
+       }
+}
 
 int main()
 {
@@ -2343,5 +2368,6 @@ int main()
        test_variant();
        test_integer128();
        test_c_native_types();
+       test_optional();
        return 0;
 }
This page took 0.029106 seconds and 4 git commands to generate.