Comparing C style struct with 'member' functions to a C++ class in an attempt to model C++ overheads, I suspected that the following implementation would be roughly equivlent by containing the same number of instructions. I see that the C implementation results in extra instuctions when calling the 'member' functions.
int main()
{
uint32_t a;
rectangle_t r;
/* struct */
r.set(2,3, &r);
/* asm
ldr r3, [r7, #12]
adds r2, r7, #4
movs r1, #3
movs r0, #2
blx r3
*/
a = r.getArea(&r);
/* asm
ldr r3, [r7, #16]
adds r2, r7, #4
mov r0, r2
blx r3
str r0, [r7, #20]
movs r3, #0
*/
/* Class */
r.set(2, 3);
/* asm
adds r3, r7, #4
movs r2, #3
movs r1, #2
mov r0, r3
bl rectangle_t::set(unsigned int, unsigned int)
*/
a = r.getArea();
/* asm
adds r3, r7, #4
mov r0, r3
bl rectangle_t::getArea()
str r0, [r7, #12]
movs r3, #0
*/
}
Why is there an extra ldr instruction when calling a stuct 'member' vs a class member?
Compiler: ARM GCC 12.2.0 (linux)
Declarations:
typedef struct rectangle rectangle_t;
struct rectangle
{
uint32_t w;
uint32_t l;
void (*set)(uint32_t L, uint32_t W, rectangle_t *self);
uint32_t (*getArea)(rectangle_t *self);
};
void set(uint32_t L, uint32_t W, rectangle_t *self)
{
self->w = W;
self->l = L;
}
uint32_t getArea(rectangle_t *self)
{
return self->l * self->w;
}
class rectangle_t
{
public:
uint32_t w;
uint32_t l;
void set(uint32_t L, uint32_t W);
uint32_t getArea();
};
void rectangle_t::set(uint32_t L, uint32_t W)
{
w = W;
l = L;
}
uint32_t rectangle_t::getArea()
{
return l * w;
}