Skip to content

Commit

Permalink
debugability: Macro Metaprogramming Refactor
Browse files Browse the repository at this point in the history
Added macro functions to make repetitive, nearly identical functions more maintainable via metaprogramming. They generate code in pre-compile, conceptually similar to C++17 if-constexpr.  sof/trace, host/trace: rewrote _trace_event/d+ functions using preproc.h. test/cmocka/include/test_group_generator: rewrote macros to not conflict with new ones. Added unit tests to check whether more advanced and less obvious macros do in fact work.

Signed-off-by: Michal Jerzy Wierzbicki <[email protected]>
  • Loading branch information
mwierzbix committed Nov 2, 2018
1 parent 1024e94 commit b284ac3
Show file tree
Hide file tree
Showing 17 changed files with 1,680 additions and 825 deletions.
187 changes: 69 additions & 118 deletions src/host/trace.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
* Ranjani Sridharan <[email protected]>
*/

#include <sof/preproc.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
Expand Down Expand Up @@ -142,134 +143,84 @@ static char *get_trace_class(uint32_t trace_class)
return "value";
}

/* print trace event */
void _trace_event0(uint32_t event)
{
char a, b, c;
char *trace_class = NULL;

if (test_bench_trace > 0) {
a = event & 0xff;
b = (event >> 8) & 0xff;
c = (event >> 16) & 0xff;
#define META_SEQ_STEP_param_procD(i, _) META_CONCAT(param, i) %d

/* look up subsystem from trace class table */
trace_class = strdup(get_trace_class(event >> 24));

/* print trace event stderr*/
if (strcmp(trace_class, "value") == 0)
fprintf(stderr, "Trace value %d\n", event);
else
fprintf(stderr, "Trace %s %c%c%c\n", trace_class,
c, b, a);
}

free(trace_class);
}

void _trace_event_mbox_atomic0(uint32_t event)
{
_trace_event0(event);
}
#define HOST_TRACE_EVENT_NTH(postfix, vararg_count)\
META_FUNC_WITH_VARARGS(_trace_event, postfix, void,\
META_CONCAT(, uint32_t event),\
vararg_count, META_SEQ_STEP_param_uint32_t)

/* print trace event */
void _trace_event1(uint32_t event, uint32_t param)
{
char a, b, c;
char *trace_class = NULL;

if (test_bench_trace > 0) {
a = event & 0xff;
b = (event >> 8) & 0xff;
c = (event >> 16) & 0xff;

/* look up subsystem from trace class table */
trace_class = strdup(get_trace_class(event >> 24));

/* print trace event stderr*/
if (strcmp(trace_class, "value") == 0)
fprintf(stderr, "Trace value %d, param1 %d\n", event,
param);
else
fprintf(stderr, "Trace %s %c%c%c\n", trace_class,
c, b, a);
}

free(trace_class);
#define HOST_TRACE_EVENT_NTH_IMPL(arg_count)\
HOST_TRACE_EVENT_NTH(, arg_count)\
{\
char a, b, c;\
\
if (test_bench_trace > 0) {\
/* look up subsystem from trace class table */\
char *trace_class = strdup(get_trace_class(event >> 24));\
\
a = event & 0xff;\
b = (event >> 8) & 0xff;\
c = (event >> 16) & 0xff;\
\
/* print trace event stderr*/\
if (!strcmp(trace_class, "value"))\
fprintf(stderr,\
"Trace value %d, "META_QUOTE(\
META_SEQ_FROM_0_TO(\
arg_count, META_SEQ_STEP_param_procD\
))"\n"\
, event META_SEQ_FROM_0_TO(arg_count, META_SEQ_STEP_param));\
else\
fprintf(stderr,\
"Trace %s %c%c%c\n"\
, trace_class, c, b, a);\
if (trace_class)\
free(trace_class);\
}\
}\
HOST_TRACE_EVENT_NTH(_mbox_atomic, arg_count)\
{\
META_CONCAT(_trace_event, arg_count)\
(event META_SEQ_FROM_0_TO(arg_count,META_SEQ_STEP_param));\
}

void _trace_event_mbox_atomic1(uint32_t event, uint32_t param)
{
_trace_event1(event, param);
}

/* print trace event */
void _trace_event2(uint32_t event, uint32_t param1, uint32_t param2)
{
char a, b, c;
char *trace_class = NULL;

if (test_bench_trace > 0) {
a = event & 0xff;
b = (event >> 8) & 0xff;
c = (event >> 16) & 0xff;

/* look up subsystem from trace class table */
trace_class = strdup(get_trace_class(event >> 24));

/* print trace event stderr*/
if (strcmp(trace_class, "value") == 0)
fprintf(stderr,
"Trace value %d, param1 %d param2 %d\n",
event, param1, param2);
else
fprintf(stderr, "Trace %s %c%c%c\n", trace_class,
c, b, a);
}

free(trace_class);
}

void _trace_event_mbox_atomic2(uint32_t event, uint32_t param1,
uint32_t param2)
{
_trace_event2(event, param1, param2);
}

/* print trace event */
void _trace_event3(uint32_t event, uint32_t param1, uint32_t param2,
uint32_t param3)
{
char a, b, c;
char *trace_class = NULL;
/* Implementation of
* void _trace_event0( uint32_t log_entry, uint32_t params...) {...}
* void _trace_event_mbox_atomic0(uint32_t log_entry, uint32_t params...) {...}
*/
HOST_TRACE_EVENT_NTH_IMPL(0);

if (test_bench_trace > 0) {
a = event & 0xff;
b = (event >> 8) & 0xff;
c = (event >> 16) & 0xff;
/* Implementation of
* void _trace_event1( uint32_t log_entry, uint32_t params...) {...}
* void _trace_event_mbox_atomic1(uint32_t log_entry, uint32_t params...) {...}
*/
HOST_TRACE_EVENT_NTH_IMPL(1);

/* look up subsystem from trace class table */
trace_class = strdup(get_trace_class(event >> 24));
/* Implementation of
* void _trace_event2( uint32_t log_entry, uint32_t params...) {...}
* void _trace_event_mbox_atomic2(uint32_t log_entry, uint32_t params...) {...}
*/
HOST_TRACE_EVENT_NTH_IMPL(2);

/* print trace event stderr*/
if (strcmp(trace_class, "value") == 0)
fprintf
(stderr,
"Trace value %d, param1 %d param2 %d param3 %d\n",
event, param1, param2, param3);
else
fprintf(stderr, "Trace %s %c%c%c\n", trace_class,
c, b, a);
}
/* Implementation of
* void _trace_event3( uint32_t log_entry, uint32_t params...) {...}
* void _trace_event_mbox_atomic3(uint32_t log_entry, uint32_t params...) {...}
*/
HOST_TRACE_EVENT_NTH_IMPL(3);

free(trace_class);
}
/* Implementation of
* void _trace_event4( uint32_t log_entry, uint32_t params...) {...}
* void _trace_event_mbox_atomic4(uint32_t log_entry, uint32_t params...) {...}
*/
HOST_TRACE_EVENT_NTH_IMPL(4);

void _trace_event_mbox_atomic3(uint32_t event, uint32_t param1,
uint32_t param2, uint32_t param3)
{
_trace_event3(event, param1, param2, param3);
}
/* Implementation of
* void _trace_event5( uint32_t log_entry, uint32_t params...) {...}
* void _trace_event_mbox_atomic5(uint32_t log_entry, uint32_t params...) {...}
*/
HOST_TRACE_EVENT_NTH_IMPL(5);

/* enable trace in testbench */
void tb_enable_trace(bool enable)
Expand Down
121 changes: 121 additions & 0 deletions src/include/sof/preproc-private-dec.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
/*
* Copyright (c) 2016, Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Intel Corporation nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* Author: Michal Jerzy Wierzbicki <[email protected]>
*/

/* THIS FILE SHOULD NOT BE INCLUDED DIRECTLY */

#ifdef __INCLUDE_MACRO_METAPROGRAMMING_PRIVATE__
/* Macros defined in this file are only helpers for the macros that are
* defined in header file containing "namespace"
* __INCLUDE_MACRO_METAPROGRAMMING_PRIVATE__ .
* This combination of #ifdef and #ifndef should sufficently narrow
* the "include-ability" of this dependent header file.
* If you wish to use macros from this file directly, be *V E R Y* careful!
* HIC SUNT DRACONES
*/
#ifndef __INCLUDE_MACRO_METAPROGRAMMING_PRIVATE_DEC__
#define __INCLUDE_MACRO_METAPROGRAMMING_PRIVATE_DEC__

/* The only sane way I found to decrement values in cpreproc */
/* for instance META_DEC(3) will be tokenized to DEC_3
* and then expanded again to 2
*/
#define _META_DEC_0 0 // notice how we deal with underflow
#define _META_DEC_1 0
#define _META_DEC_2 1
#define _META_DEC_3 2
#define _META_DEC_4 3
#define _META_DEC_5 4
#define _META_DEC_6 5
#define _META_DEC_7 6
#define _META_DEC_8 7
#define _META_DEC_9 8
#define _META_DEC_10 9
#define _META_DEC_11 10
#define _META_DEC_12 11
#define _META_DEC_13 12
#define _META_DEC_14 13
#define _META_DEC_15 14
#define _META_DEC_16 15
#define _META_DEC_17 16
#define _META_DEC_18 17
#define _META_DEC_19 18
#define _META_DEC_20 19
#define _META_DEC_21 20
#define _META_DEC_22 21
#define _META_DEC_23 22
#define _META_DEC_24 23
#define _META_DEC_25 24
#define _META_DEC_26 25
#define _META_DEC_27 26
#define _META_DEC_28 27
#define _META_DEC_29 28
#define _META_DEC_30 29
#define _META_DEC_31 30
#define _META_DEC_32 31
#define _META_DEC_33 32
#define _META_DEC_34 33
#define _META_DEC_35 34
#define _META_DEC_36 35
#define _META_DEC_37 36
#define _META_DEC_38 37
#define _META_DEC_39 38
#define _META_DEC_40 39
#define _META_DEC_41 40
#define _META_DEC_42 41
#define _META_DEC_43 42
#define _META_DEC_44 43
#define _META_DEC_45 44
#define _META_DEC_46 45
#define _META_DEC_47 46
#define _META_DEC_48 47
#define _META_DEC_49 48
#define _META_DEC_50 49
#define _META_DEC_51 50
#define _META_DEC_52 51
#define _META_DEC_53 52
#define _META_DEC_54 53
#define _META_DEC_55 54
#define _META_DEC_56 55
#define _META_DEC_57 56
#define _META_DEC_58 57
#define _META_DEC_59 58
#define _META_DEC_60 59
#define _META_DEC_61 60
#define _META_DEC_62 61
#define _META_DEC_63 62
#define _META_DEC_64 63

#endif // __INCLUDE_MACRO_METAPROGRAMMING_PRIVATE_DEC__
#else
#error \
Illegal use of header file: \
can only be included from context of \
__INCLUDE_MACRO_METAPROGRAMMING_PRIVATE__
#endif // __INCLUDE_MACRO_METAPROGRAMMING_PRIVATE__
Loading

0 comments on commit b284ac3

Please sign in to comment.