Skip to content

Comments

[RFC] [*]: add support for compile-time polymorphism#8

Draft
rizlik wants to merge 1 commit intowolfSSL:mainfrom
rizlik:compiletime_polymorphism
Draft

[RFC] [*]: add support for compile-time polymorphism#8
rizlik wants to merge 1 commit intowolfSSL:mainfrom
rizlik:compiletime_polymorphism

Conversation

@rizlik
Copy link

@rizlik rizlik commented Feb 19, 2026

No description provided.

@rizlik rizlik requested a review from AlexLanzano February 19, 2026 16:18
Copy link
Member

@AlexLanzano AlexLanzano left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I love the idea but I do think this could be simplified by doing the following.

First we can remove runtime polymorphism all together.
Second, keep the driver function declarations in the driver header.

Then we can do the following:

clock.h:

#define whal_Clock_Init(NAME) whal_##NAME##_Init((NAME))
...more defines here for each API function...

#define WHAL_CLOCK_DEVICE_DECLARE(NAME, DRIVER)                                 \
    extern whal_Clock ##NAME[1];                                                \
    static inline whal_Error whal_##NAME##_Init(whal_Clock *clk) {              \
        return whal_##DRIVER##_Init(clk);                                       \
    }                                                                           \
    static inline whal_Error whal_##NAME##_Deinit(whal_Clock clk) {             \
        return whal_##DRIVER##_Deinit(clk);                                     \
    }                                                                           \
    static inline whal_Error whal_##NAME##_Enable(whal_Clock clk) {             \
        return whal_##DRIVER##_Enable(clk);                                     \
    }                                                                           \
    static inline whal_Error whal_##NAME##_Disable(whal_Clock clk) {            \
        return whal_##DRIVER##_Disable(clk);                                    \
    }                                                                           \
    static inline whal_Error whal_##NAME##_GetRate(whal_Clock clk) {            \
        return whal_##DRIVER##_GetRate(clk);                                    \
    }

#define WHAL_CLOCK_DEVICE_DEFINE(NAME, REGMAP, CFG)     \
    whal_Clock ##NAME##[1] = {                          \
        .regmap = REGMAP,                               \
        .cfg = CFG,                                     \
    }

pic32cz_curiosity_ultra.h:

WHAL_CLOCK_DEVICE_DECLARE(clock, Pic32czClockPll);

pic32cz_curiosity_ultra.c:

WHAL_CLOCK_DEVICE_DEFINE(clock, WHAL_PIC32CZ_CLOCK_REGMAP, 
    &(whal_Pic32czClock_Cfg) {
        /* 300MHz clock */
        .oscCtrlCfg = &(whal_Pic32czClockPll_OscCtrlCfg) {
            .supplyCtrl = &g_whalSupply,
            .supply = &(whal_Pic32czSupc_Supply){WHAL_PIC32CZ_SUPPLY_PLL},

            .pllInst = WHAL_PIC32CZ_PLL0,
            .refSel = WHAL_PIC32CZ_REFSEL_DFLL48M,
            .bwSel = WHAL_PIC32CZ_BWSEL_10MHz_TO_20MHz,

            .fbDiv = 225,
            .refDiv = 12,

            .outCfgCount = 1,
            .outCfg = &(whal_Pic32czClockPll_OutCfg) {
                .postDivMask = WHAL_PIC32CZ_POSTDIVMASK0,
                .outEnMask = WHAL_PIC32CZ_OUTENMASK0,
                .postDiv = 3,
            },
        },
        .mclkCfg = &(whal_Pic32czClock_MclkCfg) {
            .div = 2,
        },
        .gclkCfgCount = 1,
        .gclkCfg = &(whal_Pic32czClock_GclkCfg) {
            .gen = 0,
            .genSrc = WHAL_PIC32CZ_GENSRC_PLL0_CLOCKOUT0,
            .genDiv = 1,
        },
    }
);

main.c

#include <pic32cz_curiosity_ultra.h>
void main(void) {
    whal_Clock_Init(clock);
    ...
}

This would also make the WHAL_DRV_FN unnecessary since the define macro would guarantee the correct naming

Thoughts?

uint8_t tmp[sizeof(test)] = {0};

err = whal_Clock_Init(&g_whalClock);
err = WHAL_CLOCK_INIT(clock);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure I like having to use all caps to use this library

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know it's ugly, but I also dislike having a macro lowercase. Not sure what's best here, this way it's clear that there is more macro trick behind

*/

whal_Error whal_Pic32czClockPll_Init(whal_Clock *clkDev)
whal_Error WHAL_DRV_FN(Pic32czClockPll, init)(whal_Clock *clkDev)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like this. This will make the every driver function essentially un-grepable

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

interesting point, I want to avoid that there is some rule the driver maker must "known" about how to name function, I need to evaluate the general comment yet, so probably will not be needed

Comment on lines +19 to +23
whal_Error (*init)(whal_Clock *dev);
whal_Error (*deinit)(whal_Clock *dev);
whal_Error (*enable)(whal_Clock *dev, const void *clk);
whal_Error (*disable)(whal_Clock *dev, const void *clk);
whal_Error (*getrate)(whal_Clock *dev, size_t *rate);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Keep naming convention. First letter of functions should be capitalized. Also why remove comments?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry I'll reput commnets it wasn't intentional.

Comment on lines +46 to +59
static inline whal_Error whal_dev_##NAME##_init(void) { \
return WHAL_DRV_FN(DRIVER, init)(&whal_dev_##NAME); \
} \
static inline whal_Error whal_dev_##NAME##_deinit(void) { \
return WHAL_DRV_FN(DRIVER, deinit)(&whal_dev_##NAME); \
} \
static inline whal_Error whal_dev_##NAME##_enable(const void *clk) { \
return WHAL_DRV_FN(DRIVER, enable)(&whal_dev_##NAME, clk); \
} \
static inline whal_Error whal_dev_##NAME##_disable(const void *clk) { \
return WHAL_DRV_FN(DRIVER, disable)(&whal_dev_##NAME, clk); \
} \
static inline whal_Error whal_dev_##NAME##_getrate(size_t *rate) { \
return WHAL_DRV_FN(DRIVER, getrate)(&whal_dev_##NAME, rate); \
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't change the function naming scheme. It should be whal_Clock_Init. no need for whal_dev_

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is not the "general" function though, it's just a wrapper for the specific device. The problem is that if you name a device gpio to end up with function named whal_gpio_init() that might clash with other functions.
I think namespacing this tiny wrapper function is useful. They should never be called directly btw as the other macro expands to that

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh, agreed. Maybe rename whal_dev_ to whal_Internal_ just so it's a more clear it's not supposed to be used directly?

@AlexLanzano
Copy link
Member

AlexLanzano commented Feb 19, 2026

Hmmm, now that I think about it, compile time polymorphism may make it impossible to implement a driver that needs to use a multiplatform driver call in it's implementation.

For example, say microchip releases a new SoC pic32cz2. Let's say our current pic32cz UART driver supports this new pic32cz2 SoC but our pic32cz clock driver doesn't. Right now our pic32cz uart driver is hard coded to use the pic32cz clock driver.

Or maybe a better example is implementing a SPI flash driver. The driver implementation would need to be able to call SPI functions from any SPI driver we have. And runtime determination of which underlying spi driver to use would be unavoidable in the case where the SoC has two different SPI IPs on the same chip.

It may be best to just handle this by just calling the driver function directly in cases where the user doesnt want to use runtime polymorphism.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants