From dea07f7af00b24e3b7486198f626dec793a0b4f2 Mon Sep 17 00:00:00 2001 From: Olivier Dion Date: Tue, 15 Oct 2024 12:27:50 -0400 Subject: [PATCH] Add optional type 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 Signed-off-by: Mathieu Desnoyers --- include/side/abi/type-argument.h | 7 +++++ include/side/abi/type-description.h | 2 ++ include/side/instrumentation-c-api.h | 42 ++++++++++++++++++++++++++-- src/tracer.c | 21 ++++++++++++++ src/visit-arg-vec.c | 30 ++++++++++++++++++++ src/visit-description.c | 17 +++++++++++ src/visit-description.h | 2 ++ tests/unit/test.c | 26 +++++++++++++++++ 8 files changed, 144 insertions(+), 3 deletions(-) diff --git a/include/side/abi/type-argument.h b/include/side/abi/type-argument.h index 57ce525..4d3cb6f 100644 --- a/include/side/abi/type-argument.h +++ b/include/side/abi/type-argument.h @@ -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; diff --git a/include/side/abi/type-description.h b/include/side/abi/type-description.h index 6086857..aa30485 100644 --- a/include/side/abi/type-description.h +++ b/include/side/abi/type-description.h @@ -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; diff --git a/include/side/instrumentation-c-api.h b/include/side/instrumentation-c-api.h index 2e17d49..57f22ea 100644 --- a/include/side/instrumentation-c-api.h +++ b/include/side/instrumentation-c-api.h @@ -631,9 +631,27 @@ 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...) \ { \ @@ -1050,6 +1068,24 @@ }, \ } + +#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) \ diff --git a/src/tracer.c b/src/tracer.c index d8d6ba9..ff24388 100644 --- a/src/tracer.c +++ b/src/tracer.c @@ -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, diff --git a/src/visit-arg-vec.c b/src/visit-arg-vec.c index 1942579..bda94cc 100644 --- a/src/visit-arg-vec.c +++ b/src/visit-arg-vec.c @@ -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, "\n"); abort(); diff --git a/src/visit-description.c b/src/visit-description.c index 8475289..bbb6999 100644 --- a/src/visit-description.c +++ b/src/visit-description.c @@ -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, "\n"); abort(); diff --git a/src/visit-description.h b/src/visit-description.h index 3f9ae6b..d9a3597 100644 --- a/src/visit-description.h +++ b/src/visit-description.h @@ -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); diff --git a/tests/unit/test.c b/tests/unit/test.c index d6b11ad..90de62d 100644 --- a/tests/unit/test.c +++ b/tests/unit/test.c @@ -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; } -- 2.34.1