@embig71
I also though that 1-2 month ago But turned out that itās more complicated. E.g. we canāt be sure that a pointer to data has the same size as a pointer to a function. See here
If such tricky case exists, juggling with pointer this might be not fully portable.
Anyway, determining the pointer size in compile time would be easy but the resulting code would look ugly.
switch(sizeof(void*)) {
case 2: {
uint16_t * p = ...load prev. pointer's address...
*p = new_prev;
break;
}
case 4: {
uint32t * p = ...load prev. pointer's address...
*p = new_prev;
break;
}
case 8: {
uint64_t * p = ...load prev. pointer's address...
*p = new_prev;
break;
}
}
A linked list node contains pointers to the same nodes. We turn to the members of this structure according to the index. That is, by pointer to pointer. Donāt they have the same size within the same architecture? The only case of a strange pointer size I saw for only one case: the harvard AVR architecture, with paged memory access, and even then, for const data. Are we looking at non-linear memory architectures (like x286)? Can we give at least one example of such a controller for which pointers to different data types would be presented differently? Data, not functions.
I think they can be left at the end as long as we ensure proper alignment. Iām looking at the code and I think all it takes is an additional rounding clause in _lv_ll_init to make sure that n_size is aligned to sizeof(lv_ll_node_t *). It shouldnāt require any special code for dealing with pointer sizes.
Alignment of structure members to the size of the platform data bus, the compiler always does automatically (described in the standard). Only if you do not apply the #pragma pack () structure when declaring. By the way, what is the difference between a doubly linked list in lvgl and any other portable implementation in C / CPP? In my opinion nothing. And if you look at any of these implementations, then access to pointers to nodes is made as usual pointers, without any magic.
Strange, but the behavior has not changed. Almost all functions in lv_ll.c have to be prefixed with #pragma optimize = speed no_cse. I donāt understand why this happens.
Rounding to the nearest larger divisible by 4 or 8 can be made easier.
#ifdef LV_MEM_ENV64
/*Round the size up to 8*/
node_size = (node_size + 8) & ~7UL;
#else
/*Round the size up to 4*/
node_size = (node_size + 4) & ~3UL;
#endif
I always keep a minimum of branching in the code. Especially in cycles.
I suspect itās because of the non-trivial set functions. The optimizer might be having problems figuring out what memory is being touched.
@kisvegabor Why do we need a for loop for the setter functions? As long as the lv_ll_node_t structure is aligned to lv_ll_node_t *, it should be possible to just do something like act->prev = prev, right?
With the latest changes, the project is built and works at any optimization level of the ARM IAR compiler. The problem can be considered resolved. Regards.