0

Lets's say we pass a struct to a fucntion as:

struct rect {
    long llx;
    long lly;
};

long test() {

    struct rect oldRect;
    oldRect.llx = 1;
    oldRect.lly = 2;

    struct rect newRect = make_double(oldRect);
    return newRect.llx * newRect.lly;
}

struct rect make_double(struct rect r) {
    r.llx *= 2;
    r.lly *= 2;
    return r;
}

To dig deeper what actually happen when passing a struct variable, I compiled C code into assembly as below shows:

// remove some directives that affects readibility
test:
   subq $56, %rsp
   movl $1, %edi     
   movl $2, %esi    
   call make_double
   imulq    %rdx, %rax
   addq $56, %rsp
   ret

make_double:
   leaq (%rsi,%rsi), %rdx
   leaq (%rdi,%rdi), %rax
   ret

It is interesting to observe that, when passing the struct oldRect, the gcc actually copy its members into registers which will be used as arguments in make_double function. So my questions are:

Q1-Just to confirm that When passing a struct variable, the compiler will get the struct's all members and copy them to registers, is my understanding /observation correct?

Q2-Since the compiler allocated memory space for oldRect by decrementing stack pointer, but the compiler doesn't actually push 1 and 2 to oldRect.llx , oldRect.lly respectively, if this is the case, the compiler doesn't even need to decrement stack pointer in the first place?

Q3- I'm a little bit confused with this instruction:

 subq   $56, %rsp

why we have to decrement stack pointer by 56? the size of struct rect is 16, no padding is needed, so why it is not

subq   $16, %rsp
amjad
  • 3,048
  • 1
  • 11
  • 42
  • Start by reading the ABI for your specific system to learn how it's done. Afterwards you can look at the assembly to see how the code can look. – Support Ukraine Jul 20 '20 at 07:00
  • x86-64 System V passes / returns structs up to 16 bytes in a pair of registers; read the ABI doc. Q2/Q3- that looks like a missed optimization. But it can't be `sub $16, %rsp`, it has to be `8 + n*16` to re-align the stack by 16 before another call. So `8` or a dummy `push` would have made sense. – Peter Cordes Jul 20 '20 at 07:00
  • @PeterCordes thanks. so for my Q2, why compilert need to decrement stack pointer in the first place as nothing is pushed to stack? – amjad Jul 20 '20 at 07:05
  • Because the ABI requires 16-byte alignment for RSP before every `call`, as always. – Peter Cordes Jul 20 '20 at 07:07
  • 1
    In C when you pass by value.......you pass by value.....a copy of what you passed is sent to the function. – old_timer Jul 20 '20 at 07:13

0 Answers0